POJ 2752 (字符串中找即是前缀又是后缀的子串)

Seek the Name, Seek the Fame
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 24200 Accepted: 12618
Description

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

题意:从一个字符串中找到既是前缀又是后缀的字符串,从小到大输出他们的长度

解答:答案就是next数组,但是要注意的是next数组没有包括自身

AC code

#include 
#include 
#include 
#include 
#include 
#include 

using namespace std;

#define maxn 400005
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
int nxt[maxn];
int m,t;
char p[maxn];
vector<int> ans;

int main(){

    while(scanf("%s", p+1) != EOF){
        ans.clear(); // 清空数组
        m = strlen(p+1);
        nxt[0] = -1;
        int j = -1;
        for(int i=1; i<=m; i++){
            while(j>=0 && p[j+1]!=p[i]) j = nxt[j];
            nxt[i] = ++j;
        }
        while(m){                
            ans.push_back(m);  // 先加入自身长度 
            m = nxt[m];        // 与p[1...m]自身前后缀相同的不断往上遍历 
        }
        // 倒着输出 
        reverse(ans.begin(), ans.end());
        for(int i=0; icout << ans[i];
            if(i== ans.size()-1) cout << '\n';
            else cout << ' ' ; 
        }
    }       
    return 0;
}

你可能感兴趣的:(KMP,ACM算法日常)