1. 程式人生 > >Kuangbin專題十六KMP & 擴充套件KMP & Manacher(A~L)

Kuangbin專題十六KMP & 擴充套件KMP & Manacher(A~L)

Given two sequences of numbers : a[1], a[2], ...... , a[N], and b[1], b[2], ...... , b[M] (1 <= M <= 10000, 1 <= N <= 1000000). Your task is to find a number K which make a[K] = b[1], a[K + 1] = b[2], ...... , a[K + M - 1] = b[M]. If there are more than one K exist, output the smallest one. 

Input

The first line of input is a number T which indicate the number of cases. Each case contains three lines. The first line is two numbers N and M (1 <= M <= 10000, 1 <= N <= 1000000). The second line contains N integers which indicate a[1], a[2], ...... , a[N]. The third line contains M integers which indicate b[1], b[2], ...... , b[M]. All integers are in the range of [-1000000, 1000000]. 

Output

For each test case, you should output one line which only contain K described above. If no such K exists, output -1 instead. 

Sample Input

2
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 1 3
13 5
1 2 1 2 3 1 2 3 1 3 2 1 2
1 2 3 2 1

Sample Output

6
-1

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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

int nxt[N];
void getnext(int * s, int n)
{
    nxt[0] = -1;
    int k = -1;
    for(int i = 0; i < n; ) {
        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 kmp(int * a, int * b, int n, int m)
{
    int k = 0;
    for(int i = 0; i < n; ) {
        if(k == -1 || a[i] == b[k]) {
            i++; k++;
        }
        else k = nxt[k];
//cout << "k " << k << endl;
        if(k == m) return i - m + 1;
    }
    return -1;
}

int a[N], b[N], n, m;

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

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

    while(t--) {
        scanf("%d%d", &n, &m);
        rep(i, 0, n - 1) scanf("%d", &a[i]);
        rep(i, 0, m - 1) scanf("%d", &b[i]);
        getnext(b, m);
//rep(i, 0, m - 1) printf("%d ", nxt[i]);puts("");
        printf("%d\n", kmp(a, b, n, m));
    }

    return 0;
}


The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book:  Tout avait Pair normal, mais tout s’affirmait faux. Tout avait Fair normal, d’abord, puis surgissait l’inhumain, l’affolant. Il aurait voulu savoir où s’articulait l’association qui l’unissait au roman : stir son tapis, assaillant à tout instant son imagination, l’intuition d’un tabou, la vision d’un mal obscur, d’un quoi vacant, d’un non-dit : la vision, l’avision d’un oubli commandant tout, où s’abolissait la raison : tout avait l’air normal mais…  Perec would probably have scored high (or rather, low) in the following contest. People are asked to write a perhaps even meaningful text on some subject with as few occurrences of a given “word” as possible. Our task is to provide the jury with a program that counts these occurrences, in order to obtain a ranking of the competitors. These competitors often write very long texts with nonsense meaning; a sequence of 500,000 consecutive 'T's is not unusual. And they never use spaces.  So we want to quickly find out how often a word, i.e., a given string, occurs in a text. More formally: given the alphabet {'A', 'B', 'C', …, 'Z'} and two finite strings over that alphabet, a word W and a text T, count the number of occurrences of W in T. All the consecutive characters of W must exactly match consecutive characters of T. Occurrences may overlap.   

Input

The first line of the input file contains a single number: the number of test cases to follow. Each test case has the following format:  One line with the word W, a string over {'A', 'B', 'C', …, 'Z'}, with 1 ≤ |W| ≤ 10,000 (here |W| denotes the length of the string W).  One line with the text T, a string over {'A', 'B', 'C', …, 'Z'}, with |W| ≤ |T| ≤ 1,000,000. 

Output

For every test case in the input file, the output should contain a single number, on a single line: the number of occurrences of the word W in the text T.   

Sample Input

3
BAPC
BAPC
AZA
AZAZAZA
VERDI
AVERDXIVYERDIAN

Sample Output

1
3
0

數a串在b串中的數量,kmp板子題。

a串在b中可重複,所以匹配到一個後回溯是k = nxt[k]。

#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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

int nxt[N];
void getnext(char * s, int n)
{
    nxt[0] = -1;
    int k = -1;
    for(int i = 0; i < n; ) {
        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 kmp(char * a, char * b, int n, int m)
{
    int k = 0, cnt = 0;
    for(int i = 0; i < n; ) {
        if(k == -1 || a[i] == b[k]) {
            i++; k++;
        }
        else k = nxt[k];
//cout << "k " << k <<endl;
        if(k == m) {
            cnt++; k = nxt[k];
        }
    }
    return cnt;
}

char a[N], b[N];
int n, m;

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

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

    while(t--) {
        scanf("%s%s", b, a);
        n = strlen(a); m = strlen(b);
        getnext(b, m);
   // rep(i, 0, m) printf("%d ", nxt[i]); puts("");
        printf("%d\n", kmp(a, b, n, m));
    }

    return 0;
}


一塊花布條,裡面有些圖案,另有一塊直接可用的小飾條,裡面也有一些圖案。對於給定的花布條和小飾條,計算一下能從花布條中儘可能剪出幾塊小飾條來呢? 

Input

輸入中含有一些資料,分別是成對出現的花布條和小飾條,其布條都是用可見ASCII字元表示的,可見的ASCII字元有多少個,布條的花紋也有多少種花樣。花紋條和小飾條不會超過1000個字元長。如果遇見#字元,則不再進行工作。 

Output

輸出能從花紋布中剪出的最多小飾條個數,如果一塊都沒有,那就老老實實輸出0,每個結果之間應換行。 

Sample Input

abcde a3
aaaaaa  aa
#

Sample Output

0
3

數a串在b串中的數量,kmp板子題。

a串在b中不可重複,所以匹配到一個後回溯是k = 0。

#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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

int nxt[N];
void getnext(char * s, int n)
{
    nxt[0] = -1;
    int k = -1;
    for(int i = 0; i < n; ) {
        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 kmp(char * a, char * b, int n, int m)
{
    int k = 0, cnt = 0;
    for(int i = 0; i < n; ) {
        if(k == -1 || a[i] == b[k]) {
            i++; k++;
        }
        else k = nxt[k];
//cout << "k " << k <<endl;
        if(k == m) {
            cnt++; k = 0;
        }
    }
    return cnt;
}

char a[N], b[N];
int n, m;

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

    while(true) {
        scanf("%s", a);
        if(a[0] == '#') break;
        scanf("%s", b);
        n = strlen(a); m = strlen(b);
        getnext(b, m);
   // rep(i, 0, m) printf("%d ", nxt[i]); puts("");
        printf("%d\n", kmp(a, b, n, m));
    }

    return 0;
}

CC always becomes very depressed at the end of this month, he has checked his credit card yesterday, without any surprise, there are only 99.9 yuan left. he is too distressed and thinking about how to tide over the last days. Being inspired by the entrepreneurial spirit of "HDU CakeMan", he wants to sell some little things to make money. Of course, this is not an easy task.  As Christmas is around the corner, Boys are busy in choosing christmas presents to send to their girlfriends. It is believed that chain bracelet is a good choice. However, Things are not always so simple, as is known to everyone, girl's fond of the colorful decoration to make bracelet appears vivid and lively, meanwhile they want to display their mature side as college students. after CC understands the girls demands, he intends to sell the chain bracelet called CharmBracelet. The CharmBracelet is made up with colorful pearls to show girls' lively, and the most important thing is that it must be connected by a cyclic chain which means the color of pearls are cyclic connected from the left to right. And the cyclic count must be more than one. If you connect the leftmost pearl and the rightmost pearl of such chain, you can make a CharmBracelet. Just like the pictrue below, this CharmBracelet's cycle is 9 and its cyclic count is 2: 

Now CC has brought in some ordinary bracelet chains, he wants to buy minimum number of pearls to make CharmBracelets so that he can save more money. but when remaking the bracelet, he can only add color pearls to the left end and right end of the chain, that is to say, adding to the middle is forbidden.  CC is satisfied with his ideas and ask you for help.

Input

The first line of the input is a single integer T ( 0 < T <= 100 ) which means the number of test cases.  Each test case contains only one line describe the original ordinary chain to be remade. Each character in the string stands for one pearl and there are 26 kinds of pearls being described by 'a' ~'z' characters. The length of the string Len: ( 3 <= Len <= 100000 ).

Output

For each case, you are required to output the minimum count of pearls added to make a CharmBracelet.

Sample Input

3
aaa
abca
abcde

Sample Output

0
2
5

給一個串,求最少加多少字元使其為週期串。

當它本來就是週期串時輸出0,否則最後一段就是週期的一部分,輸出該補的長度就行。

比如abcabcabc是週期串輸出0,而abcabca最後的a是迴圈節abc的一部分,該補上bc的長度2。

判斷週期串是:int len = ls - nxt[ls]; len != ls && ls % len == 0這兩句,當len是ls的因子時就是週期串。 如果不是週期串,那麼len的串是最小迴圈節的一部分,len - nxt[ls] % len是減去已經匹配的部分。

#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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

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

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

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

    while(t--) {
        scanf("%s", s);
        ls = strlen(s);
        getnext(s, ls);
        int len = ls - nxt[ls];
        if(len != ls && ls % len == 0) puts("0");
        else printf("%d\n", len - nxt[ls] % len);
    }

    return 0;
}


For each prefix of a given string S with N characters (each character has an ASCII code between 97 and 126, inclusive), we want to know whether the prefix is a periodic string. That is, for each i (2 <= i <= N) we want to know the largest K > 1 (if there is one) such that the prefix of S with length i can be written as A K , that is A concatenated K times, for some string A. Of course, we also want to know the period K. 

Input

The input file consists of several test cases. Each test case consists of two lines. The first one contains N (2 <= N <= 1 000 000) – the size of the string S. The second line contains the string S. The input file ends with a line, having the number zero on it. 

Output

For each test case, output “Test case #” and the consecutive test case number on a single line; then, for each prefix with length i that has a period K > 1, output the prefix size i and the period K separated by a single space; the prefix sizes must be in increasing order. Print a blank line after each test case. 

Sample Input

3
aaa
12
aabaabaabaab
0

Sample Output

Test case #1
2 2
3 3

Test case #2
2 2
6 2
9 3
12 4

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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

int n;
char s[N];

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

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

    int Case = 1;
    while(scanf("%d", &n) && n) {
        scanf("%s", s);
        getnxt(s, n);
        printf("Test case #%d\n", Case++);
        rep(i, 1, n) {
            if(nxt[i] <= 0) continue;
            int len = i - nxt[i];
            if(i % len == 0) printf("%d %d\n", i, i / len);
        }
        puts("");
    }

    return 0;
}

There is a string A. The length of A is less than 1,000,000. I rewrite it again and again. Then I got a new string: AAAAAA...... Now I cut it from two different position and get a new string B. Then, give you the string B, can you tell me the length of the shortest possible string A.  For example, A="abcdefg". I got abcd efgabcdefgabcdefgabcdefg.... Then I cut the red part: efgabcdefgabcde as string B. From B, you should find out the shortest A.   

Input

Multiply Test Cases.  For each line there is a string B which contains only lowercase and uppercase charactors.  The length of B is no more than 1,000,000. 

Output

For each line, output an integer, as described above.

Sample Input

bcabcab
efgabcdefgabcde

Sample Output

3
7

給你串求將其補成周期串的最小迴圈節長度。

如果B是週期串,顯然ls - nxt[ls]

如果不是那麼ls - nxt[ls]就是該串把尾巴多的非週期部分去掉,得到最小迴圈節。

#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 1000010
#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++)

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

char s[N];
int ls;

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

    while(~scanf("%s", s)) {
        ls = strlen(s);
        getnxt(s, ls);
        if(ls == 1) puts("1");
        else printf("%d\n", ls - nxt[ls]);
    }

    return 0;
}

Given two strings a and b we define a*b to be their concatenation. For example, if a = "abc" and b = "def" then a*b = "abcdef". If we think of concatenation as multiplication, exponentiation by a non-negative integer is defined in the normal way: a^0 = "" (the empty string) and a^(n+1) = a*(a^n).

Input

Each test case is a line of input representing s, a string of printable characters. The length of s will be at least 1 and will not exceed 1 million characters. A line containing a period follows the last test case.

Output

For each s you should print the largest n such that s = a^n for some string a.

Sample Input

abcd
aaaa
ababab
.

Sample Output

1
4
3

Hint

This problem has huge input, use scanf instead of cin to avoid time limit exceed.

最小迴圈節週期串。

#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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

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

char s[N];
int ls;

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

    while(scanf("%s", s) && s[0] != '.') {
        ls = strlen(s);
        getnxt(s, ls);
        if(ls % (ls - nxt[ls])) puts("1");
        else printf("%d\n", ls / (ls - nxt[ls]));
    }

    return 0;
}

The little cat is so famous, that many couples tramp over hill and dale to Byteland, and asked the little cat to give names to their newly-born babies. They seek the name, and at the same time seek the fame. In order to escape from such boring job, the innovative little cat works out an easy but fantastic algorithm:  Step1. Connect the father's name and the mother's name, to a new string S.  Step2. Find a proper prefix-suffix string of S (which is not only the prefix, but also the suffix of S).  Example: Father='ala', Mother='la', we have S = 'ala'+'la' = 'alala'. Potential prefix-suffix strings of S are {'a', 'ala', 'alala'}. Given the string S, could you help the little cat to write a program to calculate the length of possible prefix-suffix strings of S? (He might thank you by giving your baby a name:) 

Input

The input contains a number of test cases. Each test case occupies a single line that contains the string S described above.  Restrictions: Only lowercase letters may appear in the input. 1 <= Length of S <= 400000. 

Output

For each test case, output a single line with integer numbers in increasing order, denoting the possible length of the new baby's name.

Sample Input

ababcababababcabab
aaaaa

Sample Output

2 4 9 18
1 2 3 4 5

求字首等於字尾的子串。nxt陣列的意義就是字首等於字尾的長度,所以p指標直接移到nxt[p],nxt[p]~p之間是不可能有答案的,因為如果p是匹配中的一元,那麼肯定nxt[p]>=p,矛盾。

#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<double, double> P;
typedef long long ll;
#define N 1000010
#define M 2000100
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++)

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

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

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

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

    return 0;
}

The Genographic Project is a research partnership between IBM and The National Geographic Society that is analyzing DNA from hundreds of thousands of contributors to map how the Earth was populated.  As an IBM researcher, you have been tasked with writing a program that will find commonalities amongst given snippets of DNA that can be correlated with individual survey information to identify new genetic markers.  A DNA base sequence is noted by listing the nitrogen bases in the order in which they are found in the molecule. There are four bases: adenine (A), thymine (T), guanine (G), and cytosine (C). A 6-base DNA sequence could be represented as TAGACC. Given a set of DNA base sequences, determine the longest series of bases that occurs in all of the sequences.

Input

Input to this problem will begin with a line containing a single integer n indicating the number of datasets. Each dataset consists of the following components:

  • A single positive integer m (2 <= m <= 10) indicating the number of base sequences in this dataset.
  • m lines each containing a single base sequence consisting of 60 bases.

Output

For each dataset in the input, output the longest base subsequence common to all of the given base sequences. If the longest common subsequence is less than three bases in length, display the string "no significant commonalities" instead. If multiple subsequences of the same longest length exist, output only the subsequence that comes first in alphabetical order.

Sample Input

3
2
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
3
GATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATACCAGATA
GATACTAGATACTAGATACTAGATACTAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
GATACCAGATACCAGATACCAGATACCAAAGGAAAGGGAAAAGGGGAAAAAGGGGGAAAA
3
CATCATCATCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
ACATCATCATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AACATCATCATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT

Sample Output

no significant commonalities
AGATAC
CATCATCAT

emmmmmmmmmmmmm暴力列舉一個串的子串來匹配

#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<double, double> P;
typedef long long ll;
#define N 100
#define M 2000100
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++)

int nxt[N];
void getnxt(char * s, int n)
{
    int k = -1;  nxt[0] = -1;
    for(int i = 0; i < n; ) {
        if(k == -1 || s[i] == s[k]) nxt[++i] = ++k;
        else k = nxt[k];
    }
}
bool kmp(char * a, char * b, int la, int lb)
{
// int la = strlen(a), lb = strlen(b);
    getnxt(b, lb);
//cout << a << endl;
    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;
}

char s[15][100];
char sub[100], ans[100];
int lans;
int main()
{
    #ifndef ONLINE_JUDGE
    freopen("data.txt", "r", stdin);
    #endif

    int t, m;
    scanf("%d", &t);
    while(t--) {
        scanf("%d", &m);
        rep(i, 1, m) scanf("%s", s[i]);
        rep(i, 0, 60) ans[i] = 'z'; ans[61] = '\0';
        lans = 0;
//cout << s[1] <<endl;
        for(int l = 60; l >= 3; l--) {//cout <<l << endl;
            for(int i = 0; i + l <= 60; i++) {
                for(int j = i; j < l + i; j++) sub[j - i] = s[1][j];
                sub[l + i] = '\0';
//cout << sub <<endl;
                bool flag = true;
                for(int j = 2; j <= m; j++) {
                    if(!kmp(s[j], sub, 60, l)) {
                        flag = false; break;
                    }
                }
                if(flag) {
           // cout << sub << ' ' << lans << ' '<< endl;
                    if(lans < l) strcpy(ans, sub), lans = l;
                    else if(lans == l && strcmp(ans, sub) > 0)
                        strcpy(ans, sub);
                }
            }
            if(lans > 0) {
                printf("%s\n", ans);
                break;
            }
        }
        if(!lans) puts("no significant commonalities");
    }

    return 0;
}

Homer: Marge, I just figured out a way to discover some of the talents we weren’t aware we had.  Marge: Yeah, what is it?  Homer: Take me for example. I want to find out if I have a talent in politics, OK?  Marge: OK.  Homer: So I take some politician’s name, say Clinton, and try to find the length of the longest prefix  in Clinton’s name that is a suffix in my name. That’s how close I am to being a politician like Clinton  Marge: Why on earth choose the longest prefix that is a suffix???  Homer: Well, our talents are deeply hidden within ourselves, Marge.  Marge: So how close are you?  Homer: 0!  Marge: I’m not surprised.  Homer: But you know, you must have some real math talent hidden deep in you.  Marge: How come?  Homer: Riemann and Marjorie gives 3!!!  Marge: Who the heck is Riemann?  Homer: Never mind.  Write a program that, when given strings s1 and s2, finds the longest prefix of s1 that is a suffix of s2.

Input

Input consists of two lines. The first line contains s1 and the second line contains s2. You may assume all letters are in lowercase.

Output

Output consists of a single line that contains the longest string that is a prefix of s1 and a suffix of s2, followed by the length of that prefix. If the longest such string is the empty string, then the output should be 0.  The lengths of s1 and s2 will be at most 50000.

Sample Input

clinton
homer
riemann
marjorie

Sample Output

0
rie 3

輸出兩個串的字首字尾。

#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 100010
#define M 2000100
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++)

string a, b, c;
int nxt[N];

void getnxt()
{
    int n = c.length();
    nxt[0] = -1;
    int k = -1;
    for(int i = 0; i < n; ) {
        if(k == -1 || c[i] == c[k]) nxt[++i] = ++k;
        else k = nxt[k];
    }
}

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

    while(cin >> a >> b) {
        c = a + b;
        getnxt();
        if(nxt[c.length()] == 0) puts("0");
        else {
            int i = 0;
            for(i = 0; i < nxt[c.length()] && i < a.length() && i < b.length(); i++) putchar(c[i]);
            printf(" %d\n", i);
        }
    }

    return 0;
}

It is well known that AekdyCoin is good at string problems as well as number theory problems. When given a string s, we can write down all the non-empty prefixes of this string. For example:  s: "abab"  The prefixes are: "a", "ab", "aba", "abab"  For each prefix, we can count the times it matches in s. So we can see that prefix "a" matches twice, "ab" matches twice too, "aba" matches once, and "abab" matches once. Now you are asked to calculate the sum of the match times for all the prefixes. For "abab", it is 2 + 2 + 1 + 1 = 6.  The answer may be very large, so output the answer mod 10007. 

Input

The first line is a single integer T, indicating the number of test cases.  For each case, the first line is an integer n (1 <= n <= 200000), which is the length of string s. A line follows giving the string s. The characters in the strings are all lower-case letters. 

Output

For each case, output only one number: the sum of the match times for all the prefixes of s mod 10007.

Sample Input

1
4
abab

Sample Output

6

大難題啊啊啊啊啊我死了,百度下來是分段加emmmmm。

當nxt[i] + 1 != nxt[i + 1]時,說明i+1位置失配了,所以nxt[i]就是i-nxt[i]到i這段串的長度nxt[i]就是與之匹配的原串的字首長度,而字首長度就是字首串的個數Orz,也就是在i-nxt[i]到i這段串的貢獻。

#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<double, double> P;
typedef long long ll;
#define N 200010
#define M 2000100
const int INF = 0x3f3f3f3f;
const int mod = 10007;
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++)

int n, ans;
char s[N];

int nxt[N];
void getnxt(char * s, int n)
{
    nxt[n + 1] = INF;
    int k = -1; nxt[0] = -1;
    for(int i = 0; i < n; ) {
        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);
    while(t--) {
        scanf("%d%s", &n, s);
        getnxt(s, n);
//rep(i, 1, n) printf("%d ", nxt[i]);
        ans = n;
        rep(i, 2, n) if(nxt[i] + 1 != nxt[i + 1]) {
            ans += nxt[i];
            ans %= mod;
        }
        printf("%d\n", ans);
    }

    return 0;
}

Clairewd is a member of FBI. After several years concealing in BUPT, she intercepted some important messages and she was preparing for sending it to ykwd. They had agreed that each letter of these messages would be transfered to another one according to a conversion table.  Unfortunately, GFW(someone's name, not what you just think about) has detected their action. He also got their conversion table by some unknown methods before. Clairewd was so clever and vigilant that when she realized that somebody was monitoring their action, she just stopped transmitting messages.  But GFW knows that Clairewd would always firstly send the ciphertext and then plaintext(Note that they won't overlap each other). But he doesn't know how to separate the text because he has no idea about the whole message. However, he thinks that recovering the shortest possible text is not a hard task for you.  Now GFW will give you the intercepted text and the conversion table. You should help him work out this problem. 

Input

The first line contains only one integer T, which is the number of test cases.  Each test case contains two lines. The first line of each test case is the conversion table S. S[i] is the ith latin letter's cryptographic letter. The second line is the intercepted text which has n letters that you should recover. It is possible that the text is complete. 

Hint

Range of test data:  T<= 100 ;  n<= 100000; 

Output

For each test case, output one line contains the shorest possible complete text.

Sample Input

2
abcdefghijklmnopqrstuvwxyz
abcdab
qwertyuiopasdfghjklzxcvbnm
qwertabcde

Sample Output

abcdabcd
qwertabcde

這題題意賊難理解。其實是給一個串,這個串前部分是密文,後部分是明文(可能空),但是明文不全,要你求原文長啥樣。加密方法也給你。 其實是把串翻譯一下,正著反著翻譯我覺得都行,那就把給的串按加密方式加密一遍,那麼加密得到的串就會和原串有字首字尾相等的關係,然後擴充套件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 200010
#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++)

char tab[30], s[N], t[N];
int ls;
map<char, char> mp;

int nxt[N], ext[N];
void getnxt(char * x, int m)
{
    nxt[0] = m;
    int j = 0;
    while(j + 1 < m && x[j] == x[j + 1]) j++;
    nxt[1] = j;
    int k = 1;
    for(int i = 2; i < m; i++) {
        int p = nxt[k] + k - 1;
        int L = nxt[i - k];
        if(i + L < p + 1) nxt[i] = L;
        else {
            j = max(0, p - i + 1);
            while(i + j < m && x[i + j] == x[j]) j++;
            nxt[i] = j;
            k = i;
        }
    }
}
void exkmp(char * x, int m, char * y, int n)
{
    //memset(nxt, 0, sizeof nxt);
    //memset(ext, 0, sizeof ext);
    getnxt(x, m);
//cout << x << ' ';
//rep(i, 0, m) cout << nxt[i] << ' '; cout << endl;
    int j = 0;
    while(j < n && j < m && x[j] == y[j]) j++;
    ext[0] = j;
    int k = 0;
    for(int i = 1; i < n; i++) {
        int p = ext[k] + k - 1;
        int L = nxt[i - k];
        if(i + L < p + 1) ext[i] = L;
        else {
            j = max(0, p - i + 1);
            while(j + i < n && j < m && y[i + j] == x[j]) j++;
            ext[i] = j;
            k = i;
        }
      //  cout << k << ' ' << p << ' ' << L << ' ' << ext[i] << endl;
    }
}

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

    int T;
    scanf("%d", &T);
    while(T--) {
        scanf("%s%s", tab, s);
        ls = strlen(s);

        mp.clear();
        for(int i = 0; tab[i]; i++) mp[tab[i]] = char(i + 'a');

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

        exkmp(t, ls, s, ls);
//rep(i, 0, ls) cout << ext[i] << ' '; cout << endl;
        int i;
        for(i = 0; i < ls; i++) {
            if(ext[i] + i >= ls && i >= ext[i]) {
                break;
            }
        }
        for(int j = 0; j < i; j++) putchar(s[j]);
        for(int j = 0; j < i; j++) putchar(mp[s[j]]);

        putchar('\n');
    }

    return 0;
}