HDU 6629 string matching

string matching

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)

Problem Description

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:

HDU 6629 string matching_第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.

Sample Input

3
_Happy_New_Year_
ywwyww
zjczzzjczjczzzjc

Sample Output

17
7
32

题意:

主要题目让我们求的是每一个i开始的前缀和0开始的前缀相等,然后进行运算。

思路:

因为是前缀和前缀相等,所有只要用扩展kmp算法求出next数组的值在进行运算就行了,next数组求的是一个字符串中x[i-m - 1]前缀和x[0-m-1]的最大公共前缀。

#include 
#include 
#include 
#include 
using namespace std;
typedef long long ll;
const int maxn = 1e+6 + 10;
char s[maxn];
int Next[maxn], extend[maxn];
void GetNext(char *s, int m) {
    Next[0] = m;
    int j = 0, k = 1;
    while (j + 1 < m && s[j] == s[j + 1]) j++;
    Next[1] = j;
    for (int i = 2; i < m; i++) {
        int p = Next[k] + k - 1, L = Next[i - k];
        if (L + i < p + 1) Next[i] = L;
        else {
            j = max(0, p - i + 1);
            while (i + j < m && s[j] == s[i + j]) j++;
            Next[i] = j;
            k = i;
        }
    }
}
int main() {
    int t;
    scanf("%d", &t);
    while (t--) {
        scanf("%s", s);
        int len = strlen(s);
        GetNext(s, len);
        ll ans = 0;
        for (int i = 1; i < len; i++) {
            if (Next[i] == len - i) ans += (ll)Next[i];
            else ans += (ll)(Next[i] + 1);
        }
        printf("%lld\n", ans);
    }
    return 0;
}

你可能感兴趣的:(HDU)