【题解】string matching HDU - 6629 ⭐⭐ 【扩展KMP】

string matching HDU - 6629

String matching is a common type of problem in computer science. One string matching problem is as following:

Given a string s[0…len−1], please calculate the length of the longest common prefix of s[i…len−1] and s[0…len−1] for each i>0.

I believe everyone can do it by brute force.
The pseudo code of the brute force approach is as the following:
【题解】string matching HDU - 6629 ⭐⭐ 【扩展KMP】_第1张图片We are wondering, for any given string, what is the number of compare operations invoked if we use the above algorithm. Please tell us the answer before we attempt to run this algorithm.

Input

The first line contains an integer T, denoting the number of test cases.
Each test case contains one string in a line consisting of printable ASCII characters except space.

  • 1≤T≤30

  • string length ≤106 for every string

Output

For each test, print an integer in one line indicating the number of compare operations invoked if we run the algorithm in the statement against the input string.

Examples

Sample Input
3
Happy_New_Year
ywwyww
zjczzzjczjczzzjc
Sample Output
17
7
32

Hint




题意:

给出两个字符串, 求在上图函数中的比较次数

题解:

仔细观察一下上图的函数, 每次比较实际上就是两个串的后缀前缀匹配, 这里应该想到e-KMP中的next数组
next[i] : T[i-1…M]同T的最大匹配, 这样答案就是所有next[i]之和{0

由于S[i] = T[j]且S[i+1] != T[j+1]时会比较2次而不是一次, 所以next[i]要加1
但是如果next[i]+i == M的话, 说明后面全都相同, 则不能加1

经验小结:


#include
using namespace std;
#define ms(x, n) memset(x,n,sizeof(x));
typedef  long long LL;
const int inf = 1 << 30;
const int maxn = 1e6 + 10;

char T[maxn];
int nxt[maxn], M;
void getNext() {
    int a = 0, p = 0;
    nxt[0] = M;
    for (int i = 1; i < M; i++) {
        if (i >= p || i + nxt[i - a] >= p) {
            if (i >= p)
                p = i;
            while (p < M && T[p] == T[p - i])
                p++;
            nxt[i] = p - i;
            a = i;
        } else
            nxt[i] = nxt[i - a];
    }
}
int main() {
    int t;
    scanf("%d",&t);
    while(t--){
        scanf("%s",T);
        M = strlen(T);
        getNext();
        LL ans = 0;
        for(int i = 1; i < M; ++i){
            if(nxt[i] == M-i)
                ans += nxt[i];
            else
                ans += nxt[i]+1;
        }
        cout << ans << endl;
    }

    return 0;
}

你可能感兴趣的:(数据结构)