POJ2752 Seek the Name, Seek the Fame
阿新 • • 發佈:2018-08-24
inline [1] read pri std str print deque vector
題意
給定一個字符串s,從小到大輸出s中既是前綴又是後綴的子串的長度。
$1 \leq |s| \leq 400000 $
分析
一道kmp裸題。
設串長為n,且base 0。算出kmp失配指針後,n為最長長度,然後用fail數組往前跳即為答案,因為根據fail數組的含義,f[i]意為找到最長前綴(~f[i]-1)與後綴(~i-1)匹配,然後又因為base 0,所以數組的值都不用加1.要從小到大輸出,所以用棧存儲。
代碼
#include<cstdlib> #include<cstdio> #include<cmath> #include<cstring> #include<ctime> #include<iostream> #include<string> #include<vector> #include<list> #include<deque> #include<stack> #include<queue> #include<map> #include<set> #include<algorithm> #include<complex> #pragma GCC optimize ("O0") using namespace std; template<class T> inline T read(T&x){ T data=0; int w=1; char ch=getchar(); while(!isdigit(ch)) { if(ch==‘-‘) w=-1; ch=getchar(); } while(isdigit(ch)) data=10*data+ch-‘0‘,ch=getchar(); return x=data*w; } typedef long long ll; const int INF=0x7fffffff; char s[400010]; int f[400010]; int main() { // freopen(".in","r",stdin); // freopen(".out","w",stdout); while(~scanf("%s",s)) { int n=strlen(s); f[0]=f[1]=0; for(int i=1;i<=n;++i) { int j=f[i]; while(j&&s[j]!=s[i]) j=f[j]; f[i+1]=s[i]==s[j]?j+1:0; } stack<int>S; int x=n; while(x) { S.push(x); x=f[x]; } while(!S.empty()) { printf("%d ",S.top()); S.pop(); } printf("\n"); } // fclose(stdin); // fclose(stdout); return 0; }
POJ2752 Seek the Name, Seek the Fame