Kuangbin专题十六KMP & 扩展KMP & Manacher(M~Z)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_40379678/article/details/82903080

M - Substrings

 HDU - 1238

You are given a number of case-sensitive strings of alphabetic characters, find the largest string X, such that either X, or its inverse can be found as a substring of any of the given strings. 

Input

The first line of the input file contains a single integer t (1 <= t <= 10), the number of test cases, followed by the input data for each test case. The first line of each test case contains a single integer n (1 <= n <= 100), the number of given strings, followed by n lines, each representing one string of minimum length 1 and maximum length 100. There is no extra white space before and after a string. 

Output

There should be one line per test case containing the length of the largest string found. 

Sample Input

2
3
ABCD
BCDFF
BRCD
2
rose
orchid

Sample Output

2
2

暴力枚举+KMP

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 110
#define M 20010
const int INF = 0x3f3f3f3f;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

string s[N];
int n, ls;

int nxt1[N], nxt2[N];
void getnxt(const string & a, int * nxt)
{
    int la = a.length(), k = -1; nxt[0] = -1;
    for(int i = 0; i < la; ) {
        if(k == -1 || a[i] == a[k]) {
            if(a[++i] == a[++k]) nxt[i] = nxt[k];
            else nxt[i] = k;
        }
        else k = nxt[k];
    }
}

bool kmp(const string & a, const string & b, int * nxt)
{
    int la = a.length(), lb = b.length();
    int j = 0;
    for(int i = 0; i < lb; ) {
        if(j == -1 || b[i] == a[j]) {
            ++i; ++j;
        }
        else j = nxt[j];
//cout << j << endl;
        if(j >= la) return true;
    }
    return false;
}

string getstr(const string & a, int l, int r)
{
    string ans = "";
    rep(i, l, r - 1) ans += a[i];
    return ans;
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t;
    scanf("%d", &t);

    while(t--) {
        scanf("%d", &n);
        rep(i, 1, n) cin >> s[i];

        ls = s[1].length();

        bool f = false;
        rrep(i, ls, 1) {
            for(int j = 0; j + i <= ls; j++) {
                string tmp1 = getstr(s[1], j, j + i);
///cout << tmp1 << endl;
                getnxt(tmp1, nxt1);
                string tmp2 = tmp1;
                reverse(tmp2.begin(), tmp2.end());
                getnxt(tmp2, nxt2);
                bool flag = true;
                rep(k, 2, n) {
                    if(!kmp(tmp1, s[k], nxt1) && !kmp(tmp2, s[k], nxt2)) {
   // cout << k << ' ' << tmp1 << ' ' << s[k] << endl;
                        flag = false;
                        break;
                    }
                }
                if(flag) {
                    f = true; break;
                }
            }
            if(f) {
                printf("%d\n", i);
                break;
            }
        }

        if(!f) puts("0");
    }

    return 0;
}

N - Corporate Identity

 HDU - 2328

Beside other services, ACM helps companies to clearly state their “corporate identity”, which includes company logo but also other signs, like trademarks. One of such companies is Internet Building Masters (IBM), which has recently asked ACM for a help with their new identity. IBM do not want to change their existing logos and trademarks completely, because their customers are used to the old ones. Therefore, ACM will only change existing trademarks instead of creating new ones. 

After several other proposals, it was decided to take all existing trademarks and find the longest common sequence of letters that is contained in all of them. This sequence will be graphically emphasized to form a new logo. Then, the old trademarks may still be used while showing the new identity. 

Your task is to find such a sequence.

Input

The input contains several tasks. Each task begins with a line containing a positive integer N, the number of trademarks (2 ≤ N ≤ 4000). The number is followed by N lines, each containing one trademark. Trademarks will be composed only from lowercase letters, the length of each trademark will be at least 1 and at most 200 characters. 

After the last trademark, the next task begins. The last task is followed by a line containing zero.

Output

For each task, output a single line containing the longest string contained as a substring in all trademarks. If there are several strings of the same length, print the one that is lexicographically smallest. If there is no such non-empty string, output the words “IDENTITY LOST” instead.

Sample Input

3
aabbaabb
abbababb
bbbbbabb
2
xyz
abc
0

Sample Output

abb
IDENTITY LOST

暴力

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 210
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int nxt[N];
void getnxt(char * s, int ls)
{
    int k = -1; nxt[0] = -1;
    for(int i = 0; i < ls; ) {
        if(k == -1 || s[i] == s[k]) {
            if(s[++i] == s[++k]) nxt[i] = nxt[k];
            else nxt[i] = k;
        }
        else k = nxt[k];
    }
}

bool kmp(char * a, int la, char * b, int lb)
{
    for(int i = 0, j = 0; i < la; ) {
        if(j == -1 || a[i] == b[j]) {
            ++i; ++j;
        }
        else j = nxt[j];
        if(j == lb) return true;
    }
    return false;
}

int n, ls;
char s[4100][N], tmp[N], ans[N];

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(scanf("%d", &n) && n) {
        rep(i, 1, n) scanf("%s", s[i]);
        ls = strlen(s[1]);

        bool f = false;
        rep(i, 0, ls) ans[i] = 'z';
        ans[ls + 1] = '\0';
        rrep(i, ls, 1) {
            for(int j = 0; j + i <= ls; j++) {
                rep(k, 0, i - 1) tmp[k] = s[1][k + j];
                tmp[i] = '\0';
                getnxt(tmp, i);
//cout << tmp << endl;
                bool flag = true;
                rep(k, 2, n) {
                    if(!kmp(s[k], strlen(s[k]), tmp, i)) {
                        flag = false;
                        break;
                    }
                }
                if(flag) {
                    f = true;
                    if(strcmp(tmp, ans) < 0) strcpy(ans, tmp);
                }
            }
            if(f) break;
        }
        if(!f) puts("IDENTITY LOST");
        else puts(ans);
    }

    return 0;
}

O - String Problem

 HDU - 3374

Give you a string with length N, you can generate N strings by left shifts. For example let consider the string “SKYLONG”, we can generate seven strings: 
String Rank 
SKYLONG 1 
KYLONGS 2 
YLONGSK 3 
LONGSKY 4 
ONGSKYL 5 
NGSKYLO 6 
GSKYLON 7 
and lexicographically first of them is GSKYLON, lexicographically last is YLONGSK, both of them appear only once. 
  Your task is easy, calculate the lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), its times, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also. 

Input

  Each line contains one line the string S with length N (N <= 1000000) formed by lower case letters.

Output

Output four integers separated by one space, lexicographically fisrt string’s Rank (if there are multiple answers, choose the smallest one), the string’s times in the N generated strings, lexicographically last string’s Rank (if there are multiple answers, choose the smallest one), and its times also.

Sample Input

abcder
aaaaaa
ababab

Sample Output

1 1 6 1
1 6 1 6
1 3 2 3

串的最小表示法和最大表示法,表示出来后kmp。

当时学最大最小表示法的时候还看懂了,这会儿写博客又忘了原理了,佛了佛了当板子吧。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int nxt[N];
void getnxt(char * s, int ls)
{
    int k = -1; nxt[0] = -1;
    for(int i = 0; i < ls; ) {
        if(k == -1 || s[i] == s[k]) {
            if(s[++i] == s[++k]) nxt[i] = nxt[k];
            else nxt[i] = k;
        }
        else k = nxt[k];
    }
}

int minr(char * s, int ls)
{
    int i = 0, j = 1, k;
    while(i < ls && j < ls) {
        k = 0;
        while(s[(i + k) % ls] == s[(j + k) % ls] && k < ls) k++;
        if(k == ls) return min(i, j);
        if(s[(i + k) % ls] > s[(j + k) % ls]) i = max(i + k + 1, j + 1);
        else j = max(j + k + 1, i + 1);
    }
    return min(i, j) % ls;
}
int maxr(char * s, int ls)
{
    int i = 0, j = 1, k;
    while(i < ls && j < ls) {
        k = 0;
        while(s[(i + k) % ls] == s[(j + k) % ls] && k < ls) k++;
        if(k == ls) return min(i, j);
        if(s[(i + k) % ls] < s[(j + k) % ls]) i = max(i + k + 1, j + 1);
        else j = max(j + k + 1, i + 1);
    }
    return min(i, j) % ls;
}

char s[N];
int ls, p1, p2, ans;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%s", s)) {
        ls = strlen(s);
        p1 = minr(s, ls) + 1;
        p2 = maxr(s, ls) + 1;
        getnxt(s, ls);
        if(ls % (ls - nxt[ls]) == 0)
            ans = ls / (ls - nxt[ls]);
        else ans = 1;
        printf("%d %d %d %d\n", p1, ans, p2, ans);
    }

    return 0;
}

P - How many

 HDU - 2609

Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell me 
How many kinds of necklaces total have.(if two necklaces can equal by rotating ,we say the two necklaces are some). 
For example 0110 express a necklace, you can rotate it. 0110 -> 1100 -> 1001 -> 0011->0110. 

Input

The input contains multiple test cases. 
Each test case include: first one integers n. (2<=n<=10000) 
Next n lines follow. Each line has a equal length character string. (string only include '0','1'). 

Output

For each test case output a integer , how many different necklaces.

Sample Input

4
0110
1100
1001
0011
4
1010
0101
1000
0001

Sample Output

1
2

最大最小表示法。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

string minr(const string & s, int ls)
{
    int i = 0, j = 1, k, p;
    bool f = false;

    while(i < ls && j < ls) {
        k = 0;
        while(s[(i + k) % ls] == s[(j + k) % ls] && k < ls) k++;
        if(k == ls) {
            f = true;
            p = min(i, j);
        }
        if(s[(i + k) % ls] > s[(j + k) % ls]) i = max(i + k + 1, j + 1);
        else j = max(j + k + 1, i + 1);
    }
    if(!f) p = min(i, j) % ls;
    string ans = "";
    int cnt = ls, l = 0;
    while(cnt--) {
        ans += s[(p + l) % ls];
        l++;
    }
    return ans;
}
set<string> st;
int n;
string s;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%d", &n)) {
        st.clear();
        rep(i, 1, n) {
            cin >> s;
            st.insert(minr(s, s.length()));
        }
        printf("%d\n", (int)st.size());
    }

    return 0;
}

Q - Period II

 FZU - 1901

For each prefix with length P of a given string S,if

S[i]=S[i+P] for i in [0..SIZE(S)-p-1],

then the prefix is a “period” of S. We want to all the periodic prefixs.

Input

Input contains multiple cases.

The first line contains an integer T representing the number of cases. Then following T cases.

Each test case contains a string S (1 <= SIZE(S) <= 1000000),represents the title.S consists of lowercase ,uppercase letter.

Output

For each test case, first output one line containing "Case #x: y", where x is the case number (starting from 1) and y is the number of periodic prefixs.Then output the lengths of the periodic prefixs in ascending order.

Sample Input

4
ooo
acmacmacmacmacma
fzufzufzuf
stostootssto

Sample Output

Case #1: 3
1 2 3
Case #2: 6
3 6 9 12 15 16
Case #3: 4
3 6 9 10
Case #4: 2
9 12

求所有前缀后缀匹配的长度。和上面某某题目差不多。

首先肯定nxt[ls]是失配指针且这个匹配配到了尾巴,所以ls - nxt[ls]是答案。

然后肯定nxt[ls]到ls之间都没有失配,所以下一个失配的就是nxt[ls],或者是循环节那种。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

char s[N];
int ls;
int ans[N], l, p;

int nxt[N];
void getnxt()
{
    int k = -1; nxt[0] = -1;
    for(int i = 0; i < ls;) {
        if(k == -1 || s[i] == s[k]) nxt[++i] = ++k;
        else k = nxt[k];
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t;
    scanf("%d", &t);

    rep(Case, 1, t) {
        scanf("%s", s);
        ls = strlen(s);
        getnxt();
//rep(i, 0, ls) cout << i << ' ' << nxt[i] << endl;
        l = 0;
        p = ls;
        while(p > 0) {
            ans[l++] = ls - nxt[p];
            p = nxt[p];
        }
        sort(ans, ans + l);
        printf("Case #%d: %d\n", Case, l);
        for(int i = 0; i < l; i++) {
            printf("%d%c", ans[i], i == l - 1?'\n':' ');
        }
    }

    return 0;
}

R - Teacher YYF

 POJ - 3746

模拟没高兴写,嫌烦人,佛了佛了。

S - Best Reward

 HDU - 3613

After an uphill battle, General Li won a great victory. Now the head of state decide to reward him with honor and treasures for his great exploit. 

One of these treasures is a necklace made up of 26 different kinds of gemstones, and the length of the necklace is n. (That is to say: n gemstones are stringed together to constitute this necklace, and each of these gemstones belongs to only one of the 26 kinds.) 

In accordance with the classical view, a necklace is valuable if and only if it is a palindrome - the necklace looks the same in either direction. However, the necklace we mentioned above may not a palindrome at the beginning. So the head of state decide to cut the necklace into two part, and then give both of them to General Li. 

All gemstones of the same kind has the same value (may be positive or negative because of their quality - some kinds are beautiful while some others may looks just like normal stones). A necklace that is palindrom has value equal to the sum of its gemstones' value. while a necklace that is not palindrom has value zero. 

Now the problem is: how to cut the given necklace so that the sum of the two necklaces's value is greatest. Output this value. 
 

Input

The first line of input is a single integer T (1 ≤ T ≤ 10) - the number of test cases. The description of these test cases follows. 

For each test case, the first line is 26 integers: v 1, v 2, ..., v 26 (-100 ≤ v i≤ 100, 1 ≤ i ≤ 26), represent the value of gemstones of each kind. 

The second line of each test case is a string made up of charactor 'a' to 'z'. representing the necklace. Different charactor representing different kinds of gemstones, and the value of 'a' is v 1, the value of 'b' is v 2, ..., and so on. The length of the string is no more than 500000. 
 

Output

Output a single Integer: the maximum value General Li can get from the necklace.

Sample Input

2
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
aba
1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1
acacac

Sample Output

1
6

这题题意一开始读错了,以为项链是循环的,要切两刀完全不会写,其实只是一条链切一刀。

思路是枚举切点然后对每个切点判断两边是否是回文串。

判断是否是回文可以用马拉车或者exkmp。

Manacher:

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 500010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int val[30];
char Ma[N * 2];
int Mp[N * 2], l;

int Manacher(char * s, int len)
{
    l = 0;
    Ma[l++] = '$'; Ma[l++] = '#';
    for(int i = 0; i < len; i++) {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = 0;

    int mx = 0, id = 0;
    for(int i = 1; i < l; i++) {
        Mp[i] = mx > i?min(mx - i, Mp[2 * id - i]):1;
        while(Ma[i + Mp[i]] == Ma[i - Mp[i]]) Mp[i]++;
        if(i + Mp[i] > mx) {
            id = i;
            mx = i + Mp[i];
        }
    }
}

char s[N];
int ls, sum[N], ans, tmp;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t;
    scanf("%d", &t);

    while(t--) {
        rep(i, 0, 25) scanf("%d", &val[i]);
        scanf("%s", s);
        ls = strlen(s);

        Manacher(s, ls);

        sum[0] = 0;
        rep(i, 0, ls - 1) sum[i + 1] = val[s[i] - 'a'] + sum[i];

        ans = 0;
        rep(i, 2, ls) {
            tmp = 0;
            if(Mp[i] == i) tmp += sum[i - 1];
            //if(Mp[ls * 2 - 1 - (ls - i + 1)] + ls * 2 - 1 - (ls - i + 1) == ls * 2 - 1) tmp += sum[ls - 1] - sum[i * 2 - 1];
            if(Mp[ls + i] + ls + i == l) tmp += (sum[ls] - sum[i - 1]);
            ans = max(ans, tmp);
        }

        printf("%d\n", ans);
    }

    return 0;
}

exkmp:



#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 500010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int nxt0[N], ext0[N];
int nxt1[N], ext1[N];
void getnxt(char *s, int ls, int *nxt)
{
    nxt[0] = ls;
    int j = 0;
    while(j + 1 < ls && s[j] == s[j + 1]) j++;
    nxt[1] = j;
    int k = 1;
    for(int i = 2; i < ls; i++) {
        int R = nxt[k] + k - 1;
        int L = nxt[i - k];
        if(i + L < R + 1) nxt[i] = L;
        else {
            int j = max(0, R - i + 1);
            while(i + j < ls && s[j] == s[i + j]) j++;
            nxt[i] = j;
            k = i;
        }
    }
}
void exkmp(char *s, int ls, char *t, int lt, int *nxt, int *ext)
{
    getnxt(t, lt, nxt);
    int j = 0;
    while(j < ls && j < lt && s[j] == t[j]) j++;
    ext[0] = j;
    int k = 0;
    for(int i = 1; i < ls; i++) {
        int R = ext[k] + k - 1;
        int L = nxt[i - k];
        if(i + L < R + 1) ext[i] = L;
        else {
            int j = max(0, R - i + 1);
            while(i + j < ls && j < lt && s[i + j] == t[j]) j++;
            ext[i] = j;
            k = i;
        }
    }
}

int val[30];
char s[N], t[N];
int ls, sum[N], ans, tmp;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int T;
    scanf("%d", &T);

    while(T--) {
        rep(i, 0, 25) scanf("%d", &val[i]);
        scanf("%s", s);
        ls = strlen(s);

        sum[0] = 0;
        rep(i, 0, ls - 1) sum[i + 1] = val[s[i] - 'a'] + sum[i];

        rep(i, 0, ls - 1) t[i] = s[ls - i - 1];
        t[ls] = '\0';

        exkmp(t, ls, s, ls, nxt0, ext0);
        exkmp(s, ls, t, ls, nxt1, ext1);
//rep(i, 0, ls - 1) cout << i << ' ' << ext0[i] << ' ' << ext1[i] << endl;
//rep(i, 1, ls) cout << sum[i] << endl;
        ans = 0;
        rep(i, 1, ls - 1) {
            tmp = 0;
            int p = ls - i;
//cout << p << ' ' << ext0[p] + p << endl;
            if(ext0[p] + p >= ls) tmp += sum[i];
            if(ext1[i] + i >= ls) tmp += sum[ls] - sum[i];
//cout << ext1[i] + i <<endl;
            ans = max(ans, tmp);
        }

        printf("%d\n", ans);
    }

    return 0;
}

T - Finding Palindromes

 POJ - 3376

A word is called a palindrome if we read from right to left is as same as we read from left to right. For example, "dad", "eye" and "racecar" are all palindromes, but "odd", "see" and "orange" are not palindromes.

Given n strings, you can generate n × n pairs of them and concatenate the pairs into single words. The task is to count how many of the so generated words are palindromes.

Input

The first line of input file contains the number of strings n. The following n lines describe each string:

The i+1-th line contains the length of the i-th string li, then a single space and a string of li small letters of English alphabet.

You can assume that the total length of all strings will not exceed 2,000,000. Two strings in different line may be the same.

Output

Print out only one integer, the number of palindromes.

Sample Input

3
1 a
2 ab
2 ba

Sample Output

5

Hint

The 5 palindromes are: 
a a ba ab a ab ba ba ab 

这题好难。。。

把n个串丢进Trie图,然后用原串去匹配,原串长了就看原串长的部分是否是回文串,否则就看这个节点鞋面的串有几个回文串。

昂全部是抄的大佬的代码。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

const int MAXN = 2000000;
char buf[MAXN + 1], tmp[MAXN + 1];
int n, l[MAXN], sz[MAXN], ex[MAXN], nxt[MAXN];
char s[MAXN], t[MAXN];
ll ans;

namespace trie {
    const int MAXV = MAXN + 1, MAXE = 10000000;
    int ecnt, begin[MAXV], to[MAXE], nxt[MAXE], end[MAXV], cnt[MAXV];
    char val[MAXV];

    int id, root;

    void init() {
        ecnt = 0;
        memset(begin, -1, sizeof begin);
        id = 0;
        root = id++;
        val[root] = -1;
    }

    void addedge(int u, int v) {
        nxt[ecnt] = begin[u];
        begin[u] = ecnt;
        to[ecnt++] = v;
    }

    void ins(int sz) {
        int pos = root;
        for(int i = 0; i < sz; i++) {
            int t = s[i] - 'a';
            if(ex[i] == sz - i) cnt[pos]++;
            bool exi = 0;
            for(int now = begin[pos]; now != -1; now = nxt[now])
            if(val[to[now]] == t) {
                exi = 1;
                pos = to[now];
            }
            if(!exi) {
                int v = id++;
                addedge(pos, v);
                val[v] = t;
                pos = v;
            }
        }
        end[pos]++;
    }

    void go(int sz) {
        int pos = root;
        for(int i = 0; i < sz; i++) {
            int t = s[i] - 'a';
            bool exi = 0;
            for(int now = begin[pos]; now != -1; now = nxt[now])
            if(val[to[now]] == t) {
                exi = 1;
                pos = to[now];
            }
            if(!exi) return;
            if(end[pos]) {
                if(i < sz - 1 && ex[i + 1] == sz - i - 1) ans += end[pos];
                else if(i == sz - 1) ans += end[pos];
            }
        }
        ans += cnt[pos];
    }
}

void getnxt(int len)
{
    nxt[0] = len;
    int j = 0;
    while(j + 1 < len && t[j] == t[j + 1]) j++;
    nxt[1] = j;
    int k = 1;
    for(int i = 2; i < len; i++) {
        int P = nxt[k] + k - 1;
        int L = nxt[i - k];
        if(i + L < P + 1) nxt[i] = L;
        else {
            j = max(P - i + 1, 0);
            while(i + j < len && t[i + j] == t[j]) j++;
            nxt[i] = j;
            k = i;
        }
    }
}
void exkmp(int len)
{
    getnxt(len);
    int j = 0;
    while(j < len && s[j] == t[j]) j++;
    ex[0] = j;
    int k = 0;
    for(int i = 1; i < len; i++) {
        int P = ex[k] + k - 1;
        int L = nxt[i - k];
        if(i + L < P + 1) ex[i] = L;
        else {
            j = max(0, P - i + 1);
            while(i + j < len && s[i + j] == t[j]) j++;
            ex[i] = j;
            k = i;
        }
    }
}

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int n, tot = 0;
    scanf("%d", &n);
    rep(i, 0, n - 1) {
        scanf("%d%s", &sz[i], buf + tot);
        l[i] = tot;
        tot += sz[i];
    }
    trie::init();
///cout << "aaa" << endl;
    rep(i, 0, n - 1) {
        rep(j, 0, sz[i] - 1) s[j] = buf[l[i] + sz[i] - j - 1];
        rep(j, 0, sz[i] - 1) t[j] = buf[l[i] + j];
        s[sz[i]] = t[sz[i]] = '\0';
        exkmp(sz[i]);
        trie::ins(sz[i]);
    }
    rep(i, 0, n - 1) {
        rep(j, 0, sz[i] - 1) s[j] = buf[l[i] + j];
        rep(j, 0, sz[i] - 1) t[j] = buf[l[i] + sz[i] - j - 1];
        s[sz[i]] = t[sz[i]] = '\0';
        exkmp(sz[i]);
        trie::go(sz[i]);
    }
    printf("%lld\n", ans);

    return 0;
}

U - Palindrome

 POJ - 3974

Andy the smart computer science student was attending an algorithms class when the professor asked the students a simple question, "Can you propose an efficient algorithm to find the length of the largest palindrome in a string?" 

A string is said to be a palindrome if it reads the same both forwards and backwards, for example "madam" is a palindrome while "acm" is not. 

The students recognized that this is a classical problem but couldn't come up with a solution better than iterating over all substrings and checking whether they are palindrome or not, obviously this algorithm is not efficient at all, after a while Andy raised his hand and said "Okay, I've a better algorithm" and before he starts to explain his idea he stopped for a moment and then said "Well, I've an even better algorithm!". 

If you think you know Andy's final solution then prove it! Given a string of at most 1000000 characters find and print the length of the largest palindrome inside this string.

Input

Your program will be tested on at most 30 test cases, each test case is given as a string of at most 1000000 lowercase characters on a line by itself. The input is terminated by a line that starts with the string "END" (quotes for clarity). 

Output

For each test case in the input print the test case number and the length of the largest palindrome. 

Sample Input

abcbabcbabcba
abacacbaaaab
END

Sample Output

Case 1: 13
Case 2: 6

马拉车板子题

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
int Case = 1;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

char Ma[N * 2];
int Mp[N * 2];

int manacher(char *s, int ls)
{
    int l = 0;
    Ma[l++] = '@';
    Ma[l++] = '#';
    for(int i = 0; i< ls; i++) {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = '\0';
    int mx = 0, d = 0;
    for(int i = 0; i < l; i++) {
        Mp[i] = mx > i?min(Mp[2 * d - i], mx - i):1;
        while(Ma[i + Mp[i]] == Ma[i - Mp[i]]) Mp[i]++;
        if(i + Mp[i] > mx) {
            mx = Mp[i] + i;
            d = i;
        }
    }

    mx = 0;
    rep(i, 0, l - 1) mx = max(mx, Mp[i] - 1);
    return mx;
}

char s[N];
int ls;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(~scanf("%s", s) && s[0] != 'E') {
        ls = strlen(s);
        printf("Case %d: %d\n", Case++, manacher(s, ls));
    }

    return 0;
}

V - 吉哥系列故事――完美队形II

 HDU - 4513

吉哥又想出了一个新的完美队形游戏! 
  假设有n个人按顺序站在他的面前,他们的身高分别是h[1], h[2] ... h[n],吉哥希望从中挑出一些人,让这些人形成一个新的队形,新的队形若满足以下三点要求,则就是新的完美队形: 

  1、挑出的人保持原队形的相对顺序不变,且必须都是在原队形中连续的; 
  2、左右对称,假设有m个人形成新的队形,则第1个人和第m个人身高相同,第2个人和第m-1个人身高相同,依此类推,当然如果m是奇数,中间那个人可以任意; 
  3、从左到中间那个人,身高需保证不下降,如果用H表示新队形的高度,则H[1] <= H[2] <= H[3] .... <= H[mid]。 

  现在吉哥想知道:最多能选出多少人组成新的完美队形呢?

Input

  输入数据第一行包含一个整数T,表示总共有T组测试数据(T <= 20); 
  每组数据首先是一个整数n(1 <= n <= 100000),表示原先队形的人数,接下来一行输入n个整数,表示原队形从左到右站的人的身高(50 <= h <= 250,不排除特别矮小和高大的)。

Output

  请输出能组成完美队形的最多人数,每组输出占一行。

Sample Input

2
3
51 52 51
4
51 52 52 51

Sample Output

3
4

没看到要求在原串中连续,自闭了好一会儿一百度发现提读错了。。

在马拉车里改一下匹配条件就行了。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
int Case = 1;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int Ma[N * 2];
int Mp[N * 2];

int manacher(int *s, int ls)
{
    int l = 0;
    Ma[l++] = '@';
    Ma[l++] = '#';
    for(int i = 0; i< ls; i++) {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = '\0';
    int mx = 0, d = 0;
    for(int i = 0; i < l; i++) {
        Mp[i] = mx > i?min(Mp[2 * d - i], mx - i):1;
        while(Ma[i + Mp[i]] == Ma[i - Mp[i]]) {
            if(Ma[i + Mp[i]] != '#') {
                if(Ma[i + Mp[i]] <= Ma[i + Mp[i] - 2]) Mp[i]++;
                else break;
            }
            Mp[i]++;
        }
        if(i + Mp[i] > mx) {
            mx = Mp[i] + i;
            d = i;
        }
    }

    mx = 0;
    rep(i, 0, l - 1) mx = max(mx, Mp[i] - 1);
    return mx;
}

int s[N];
int ls;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &ls);
        rep(i, 0, ls - 1) scanf("%d", &s[i]);
        printf("%d\n", manacher(s, ls));
    }

    return 0;
}

W - Girls' research

 HDU - 3294

One day, sailormoon girls are so delighted that they intend to research about palindromic strings. Operation contains two steps: 
First step: girls will write a long string (only contains lower case) on the paper. For example, "abcde", but 'a' inside is not the real 'a', that means if we define the 'b' is the real 'a', then we can infer that 'c' is the real 'b', 'd' is the real 'c' ……, 'a' is the real 'z'. According to this, string "abcde" changes to "bcdef".
Second step: girls will find out the longest palindromic string in the given string, the length of palindromic string must be equal or more than 2.

Input

Input contains multiple cases. 
Each case contains two parts, a character and a string, they are separated by one space, the character representing the real 'a' is and the length of the string will not exceed 200000.All input must be lowercase. 
If the length of string is len, it is marked from 0 to len-1.

Output

Please execute the operation following the two steps. 
If you find one, output the start position and end position of palindromic string in a line, next line output the real palindromic string, or output "No solution!". 
If there are several answers available, please choose the string which first appears.

Sample Input

b babd
a abcd

Sample Output

0 2
aza
No solution!

把串改造一下找回文。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
int Case = 1;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

char Ma[N * 2];
int Mp[N * 2];

void manacher(char *s, int ls)
{
    int l = 0;
    Ma[l++] = '@';
    Ma[l++] = '#';
    for(int i = 0; i< ls; i++) {
        Ma[l++] = s[i];
        Ma[l++] = '#';
    }
    Ma[l] = '\0';
    int mx = 0, d = 0;
    for(int i = 0; i < l; i++) {
        Mp[i] = mx > i?min(Mp[2 * d - i], mx - i):1;
        while(Ma[i + Mp[i]] == Ma[i - Mp[i]]) {
//            if(Ma[i + Mp[i]] != '#') {
//                if(Ma[i + Mp[i]] <= Ma[i + Mp[i] - 2]) Mp[i]++;
//                else break;
//            }
            Mp[i]++;
        }
        if(i + Mp[i] > mx) {
            mx = Mp[i] + i;
            d = i;
        }
    }

    mx = 0;
    int p = 0;
    rep(i, 0, l - 1) {
        if(mx < Mp[i] - 1) {
            p = i;
            mx = Mp[i] - 1;
        }
    }
    if(mx == 1) {
        puts("No solution!");
        return;
    }
    printf("%d %d\n", (p - mx + 1) / 2 - 1, (p + mx) / 2 - 1);
    for(int i = p - mx + 1; i < p + mx; i += 2) putchar(Ma[i]);
    putchar('\n');
}

char s[N], ch;
int ls;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    while(cin >> ch) {
        scanf("%s", s);
        ls = strlen(s);

        int d = 'a' - ch;
        rep(i, 0, ls - 1) s[i] = 'a' + ((s[i] - 'a' + d + 26) % 26);
    //cout << s << endl;
        manacher(s, ls);
    }

    return 0;
}

X - 最长回文

 HDU - 3068

给出一个只由小写英文字符a,b,c...y,z组成的字符串S,求S中最长回文串的长度. 
回文就是正反读都是一样的字符串,如aba, abba等

Input

输入有多组case,不超过120组,每组输入为一行小写英文字符a,b,c...y,z组成的字符串S 
两组case之间由空行隔开(该空行不用处理) 
字符串长度len <= 110000

Output

每一行一个整数x,对应一组case,表示该组case的字符串中所包含的最长回文长度. 

Sample Input

aaaa

abab

Sample Output

4
3

板子题

Y - Wow! Such Doge!

 HDU - 4847


Chen, Adrian (November 7, 2013). “Doge Is An Ac- tually Good Internet Meme. Wow.”. Gawker. Retrieved November 22, 2013. 

Doge is an Internet meme that became popular in 2013. The meme typically con- sists of a picture of a Shiba Inu dog ac- companied by multicolored text in Comic Sans MS font in the foreground. The text, representing a kind of internal monologue, is deliberately written in broken English, and usually contains the word “wow” and the phrases “such x”, “much x”, “many x”, “very x” and “so x”. 
Kabosu, the Shiba Inu featured in the original meme, was first pictured in a 2010 blog post by Atsuko Sato, a Japanese kindergarten teacher. Afterwards, varia- tions of the pictures using overlaid Comic Sans text were posted from a Tumblr blog, Shiba Confessions. However, the use of the intentionally misspelled “doge” dates back to June 2005, when it was mentioned in an episode of Homestar Runners puppet series. 
In August 2013, images of the meme were spammed on Reddit’s r/MURICA subreddit by 4chan’s random imageboard, /b/. A search of the term doge on Google Trends shows an explosion of popularity occurring in October 2013, and more so in the following month. By November 2013, the meme had become widespread on the Internet. Google later created a Doge Easter egg: when doge meme was entered into the YouTube search bar, all of the site’s text would be displayed in colorful Comic Sans, similar to the kind used by the meme. 
The meme was ranked #12 on MTV’s list of “50 Things Pop Culture Had Us Giving Thanks For” in 2013. Io9 compared the internal dialog of the Shiba Inu dogs to lolcat-speak. The image most commonly associated with the meme is of a female Shiba Inu named Kabosu, taken from a Japanese blog documenting the dog’s daily activities. The spelling of doge has several variants, leading to debate on its actual pronunciation. On December 13, Doge was named the “top meme” of 2013 by Know Your Meme. 
In December 2013, the Dogecoin was introduced as a new cryptocurrency, making it the first cryptocurrency to be based on an Internet meme; the viral phenomenon, along with usage of the Comic Sans MS typeface, gave it “the Internet density of a large star” according to Medium writer Quinn Norton. 
In late December 2013, members of the U.S. Congress produced material in the meme’s style. Huffington Post commented that Doge was “killed” because of the Congress members’ usage of the meme. 
By early 2014, Doge’s popularity was sustained by internet communities on social media, accompanied by the rapid growth and acceptance of Dogecoin. In April 2014, Doge experienced a second major media resurgence due to revelations of the Dogecoin community’s intent to sponsor Josh Wise in NASCAR and place a picture of the Shiba Inu on his vehicle. 

—— Doge (meme). (2014, May 18). 
In Wikipedia, The Free Encyclopedia. Retrieved 02:00, May 22, 2014, from 
http://en.wikipedia.org/w/index.php?title=Doge_(meme)&oldid=609040691 

Now, Doge wants to know how many words “doge” are there in a given article. Would you like to help Doge solve this problem?

Input

An article that Doge wants to know. 
The size of the article does not exceed 64KB. The article contains only ASCII characters.

Output

Please output the number of word “doge” (case- insensitive). Refer to the samples for more details.

Sample Input

adoge
cutedo 
yourge 
blownDoge
lovelyDooge
Wow!	Such Dooooooooooooooge!!!
D0ge
dOge DOGE 
dogedoge

Sample Output

6

把串改造一下kmp。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
int Case = 1;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int nxt[10];
void getnxt(char *s, int ls)
{
    nxt[0] = -1;
    int k = -1;
    for(int i = 0; i < ls;) {
        if(k == -1 || s[i] == s[k]) nxt[++i] = ++k;
        else k = nxt[k];
    }
}
int kmp(char *s, int ls, char *p, int lp)
{
    int k = 0;
    int ans = 0;
    for(int i = 0; i < ls;) {
        if(k == -1 || s[i] == p[k]) {
            ++i; ++k;
        }
        else k = nxt[k];
        if(k == lp) {
            k  = 0;
            ans++;
        }
    }
    return ans;
}

char s[N];
int ls, cnt;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    char t[] = "doge";
    getnxt(t, 4);

    cnt = 0;
    while(~scanf("%s", s)) {
        ls = strlen(s);
        rep(i, 0, ls - 1) {
            if(isupper(s[i])) {
                s[i] = s[i] - 'A' + 'a';
            }
        }
        cnt += kmp(s, ls, t, 4);
    }
    printf("%d\n", cnt);

    return 0;
}

Z - Theme Section

 HDU - 4763

It's time for music! A lot of popular musicians are invited to join us in the music festival. Each of them will play one of their representative songs. To make the programs more interesting and challenging, the hosts are going to add some constraints to the rhythm of the songs, i.e., each song is required to have a 'theme section'. The theme section shall be played at the beginning, the middle, and the end of each song. More specifically, given a theme section E, the song will be in the format of 'EAEBE', where section A and section B could have arbitrary number of notes. Note that there are 26 types of notes, denoted by lower case letters 'a' - 'z'. 

To get well prepared for the festival, the hosts want to know the maximum possible length of the theme section of each song. Can you help us? 

Input

The integer N in the first line denotes the total number of songs in the festival. Each of the following N lines consists of one string, indicating the notes of the i-th (1 <= i <= N) song. The length of the string will not exceed 10^6.

Output

There will be N lines in the output, where the i-th line denotes the maximum possible length of the theme section of the i-th song. 

Sample Input

5
xy
abc
aaa
aaaaba
aaxoaaaaa

Sample Output

0
0
1
1
2

先用扩展kmp找出首尾相同的,然后用kmp到找见去找。

#include <cstdio>
#include <cstring>
#include <utility>
#include <iostream>
#include <map>
#include <set>
#include <queue>
#include <algorithm>
#include <cmath>
#include <string>
#include <vector>
using namespace std;
typedef pair<int, int> P;
typedef long long ll;
#define N 1000010
#define M 20010
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-5;
const double PI = acos(-1);
int Case = 1;
#define fi first
#define se second
#define rep(i, lll, nnn) for(int i = (lll); i <= (nnn); i++)
#define rrep(i, lll, nnn) for(int i = (lll); i >= (nnn); i--)

int nxt[N];
void getnxt(char *s, int ls)
{
    nxt[0] = -1;
    int k = -1;
    for(int i = 0; i < ls;) {
        if(k == -1 || s[i] == s[k]) nxt[++i] = ++k;
        else k = nxt[k];
    }
}
bool kmp(char *s, int ls, char *p, int lp)
{//cout  << s << ' ' << p << endl;
    getnxt(p, lp);
    int k = 0;
    for(int i = 0; i < ls;) {
        if(k == -1 || s[i] == p[k]) {
            ++i; ++k;
        }
        else k = nxt[k];
        if(k == lp) return true;
    }
    return false;
}

int net[N], ext[N];
void getexnxt(char *s, int ls)
{
    net[0] = ls;
    int j = 0;
    while(j + 1 < ls && s[j] == s[j + 1]) j++;
    net[1] = j;
    int k = 1;
    for(int i = 2; i < ls; i++) {
        int p = net[k] + k - 1;
        int l = net[i - k];
        if(i + l < p + 1) net[i] = l;
        else {
            j = max(0, p - i + 1);
            while(i + j < ls && s[j] == s[i + j]) j++;
            k = i;
            net[i] = j;
        }
    }
}
void exkmp(char *s, int ls, char *t, int lt)
{
    getexnxt(t, lt);
//rep(i, 0, lt - 1) cout << "net " << net[i] << endl;
    int j = 0;
    while(j < ls && j < lt && s[j] == t[j]) j++;
    ext[0] = j;
    int k = 0;
    for(int i = 1; i < ls; i++) {
        int p = ext[k] + k - 1;
        int l = net[i - k];
        if(i + l < p + 1) ext[i] = l;
        else {
            j = max(0, p - i + 1);
            while(i + j < ls && s[i + j] == t[i]) j++;
            k = i;
            ext[i] = j;
        }
    }
}

char s[N], t[N], tmp[N];
int ls, cnt;

int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int T;
    scanf("%d", &T);

    while(T--) {
        scanf("%s", s);
        ls = strlen(s);
        if(ls < 3) {
            puts("0");
            continue;
        }
        strcpy(t, s);
        exkmp(s, ls, t, ls);

        bool flag = false;
        for(int i = (ls / 3) * 2; i < ls; i++) if(ext[i] + i == ls){
            int len = ext[i];
            if(len * 3 > ls) continue;
//rep(i, 0, ls - 1) cout << "ext " << ext[i] << endl;
            if(len == 0) break;
            else {
                rep(j, len, ls - len - 1) tmp[j - len] = s[j];
                tmp[ls - 2 * len] = '\0';
                if(kmp(tmp, ls - 2 * len, s + ls - len, len)) {
                    printf("%d\n", len);
                    flag = true;
                    break;
                }
            }
        }
        if(!flag) puts("0");
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40379678/article/details/82903080