POJ - 2406 Power Strings

来源:互联网 发布:中标麒麟安装mysql 编辑:程序博客网 时间:2024/06/05 20:46

1.题面

http://poj.org/problem?id=2406

2.题意

已知一个字符串s是由某个串t经过n重复形成的

现在给你s希望你求出n最大可以是多少

3.思路

这道题用后缀数组的倍增算法写居然会超时,不得套了一个DC3算法,总算过了。

然而即使使用了DC3算法程序的运行时间依旧高达2.5ms

正解应该是kmp算法,没关系,有空我再补上。

用后缀数组有两种写法

第一种是罗穗蹇在他的pdf中介绍的,建立好height数组后,枚举t的长度k,k能整除s的长度那是必须的,除此意外要求Suffix(0+k)与Suffix(0)的最长公共前缀长度为n-k,因为从小到大枚举k所以找到一个合法的k之后就可以直接输出结果了

第二种和第一种差不多,慢了200+ms,没什么好说的,直接贴在下面了

4.代码

/*****************************************************************    > File Name: Cpp_Acm.cpp    > Author: Uncle_Sugar    > Mail: uncle_sugar@qq.com    > Created Time: 2016年07月30日 星期六 21时03分33秒*****************************************************************/# include <cstdio># include <cstring> # include <cctype># include <cmath># include <cstdlib># include <climits># include <iostream># include <iomanip># include <set># include <map># include <vector># include <stack># include <queue># include <algorithm>using namespace std;# define rep(i,a,b) for (i=a;i<=b;i++)# define rrep(i,a,b) for (i=b;i>=a;i--)template<class T>void PrintArray(T* first,T* last,char delim=' '){ for (;first!=last;first++) cout << *first << (first+1==last?'\n':delim); }const int debug = 1;const int size  = 10 + 3000000; const int INF = INT_MAX>>1;typedef long long ll;const int MAXN = 3000000 + 100;#define F(x) ((x)/3+((x)%3==1?0:tb))#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)int wa[MAXN*3],wb[MAXN*3],wv[MAXN*3],wss[MAXN*3];int c0(int *r,int a,int b){return r[a] == r[b] && r[a+1] == r[b+1] && r[a+2] == r[b+2];}int c12(int k,int *r,int a,int b){if(k == 2)return r[a] < r[b] || ( r[a] == r[b] && c12(1,r,a+1,b+1) );else return r[a] < r[b] || ( r[a] == r[b] && wv[a+1] < wv[b+1] );}void sort(int *r,int *a,int *b,int n,int m){int i;for(i = 0;i < n;i++)wv[i] = r[a[i]];for(i = 0;i < m;i++)wss[i] = 0;for(i = 0;i < n;i++)wss[wv[i]]++;for(i = 1;i < m;i++)wss[i] += wss[i-1];for(i = n-1;i >= 0;i--)b[--wss[wv[i]]] = a[i];}void dc3(int *r,int *sa,int n,int m){int i, j, *rn = r + n;int *san = sa + n, ta = 0, tb = (n+1)/3, tbc = 0, p;r[n] = r[n+1] = 0;for(i = 0;i < n;i++)if(i %3 != 0)wa[tbc++] = i;sort(r + 2, wa, wb, tbc, m);sort(r + 1, wb, wa, tbc, m);sort(r, wa, wb, tbc, m);for(p = 1, rn[F(wb[0])] = 0, i = 1;i < tbc;i++)rn[F(wb[i])] = c0(r, wb[i-1], wb[i]) ? p - 1 : p++;if(p < tbc)dc3(rn,san,tbc,p);else for(i = 0;i < tbc;i++)san[rn[i]] = i;for(i = 0;i < tbc;i++) if(san[i] < tb)wb[ta++] = san[i] * 3;if(n % 3 == 1)wb[ta++] = n - 1;sort(r, wb, wa, ta, m);for(i = 0;i < tbc;i++)wv[wb[i] = G(san[i])] = i;for(i = 0, j = 0, p = 0;i < ta && j < tbc;p++)sa[p] = c12(wb[j] % 3, r, wa[i], wb[j]) ? wa[i++] : wb[j++];for(;i < ta;p++)sa[p] = wa[i++];for(;j < tbc;p++)sa[p] = wb[j++];}//str和sa也要三倍void da(int str[],int sa[],int rank[],int height[],int n,int m){for(int i = n;i < n*3;i++)str[i] = 0;dc3(str, sa, n+1, m);int i,j,k = 0;for(i = 0;i <= n;i++)rank[sa[i]] = i;for(i = 0;i < n; i++){if(k) k--;j = sa[rank[i]-1];while(str[i+k] == str[j+k]) k++;height[rank[i]] = k;}}int str[size], sa[size], rank[size], height[size];char s[1000000+10];void Debug(int n){for (int i=1;i<=n;i++){cout << "* " << i << "*\t" << height[i] << "\t";PrintArray(str+sa[i],str+n);}for (int i=0;i<n;i++){cout << i << (i==n-1?'\n':'\t');}for (int i=0;i<n;i++){cout << rank[i] << (i==n-1?'\n':'\t');}cout << endl;}int n,k;int table[size];int main(){//# std::ios::sync_with_stdio(false);cin.tie(0);int i,j;while (~scanf("%s",s)){if (*s=='.') break;//# void da(int str[], int sa[] ,int rank[] ,int height[], int n, int m){for (i=0;s[i];i++){str[i] = s[i];}n = i;da(str,sa,rank,height,n,300);//# Debug(n);table[rank[0]] = n;for (i=rank[0]+1;i<=n;i++)table[i] = min(table[i-1],height[i]);for (i=rank[0]-1;i>=0;i--)table[i] = min(table[i+1],height[i+1]);/*Std Solution int k; for (k=1;k<=n;k++){ //# if (n%k==0&&table[rank[k]]==n-k){ //# break; //# } } printf("%d\n",n/k); *//*My Solution*/int ans = n;for (i=1;i<n;i++){//# cout << "rank[i] " << rank[i] << endl;if (table[rank[i]] == n - sa[rank[i]] && n % (n-table[rank[i]]) == 0)ans = min(ans,n-table[rank[i]]);}printf("%d\n",n/ans);}return 0;}


0 0
原创粉丝点击