zoukankan      html  css  js  c++  java
  • 【POJ 2406】Power Strings 连续重复子串

    看的《后缀数组——处理字符串的有力工具》这篇论文,在那里这道题是用后缀数组实现的,复杂度为$O(nlogn)$,很明显长度为$2×10^6$的数据会TLE,所以必需得用复杂度为$O(n)$的KMP算法。第一次写KMP,我好弱啊QAQ

    KMP:

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 2000003;
    char s[N];
    int p[N], j, n, i;
    int main() {
    	while (scanf("%s", s + 1), s[1] != '.') {
    		j = 0; n =strlen(s + 1); p[1] = 0;
    		for(i = 2; i <= n; ++i) {
    			while (j && s[j + 1] != s[i]) j = p[j];
    			if (s[j + 1] == s[i]) ++j;
    			p[i] = j;
    		}
    		printf("%d
    ", n % (n - p[n]) == 0 ? n / (n - p[n]) : 1);
    	}
    	return 0;
    }
    

    TLE的后缀数组做法:

    #include<cmath>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    const int N = 2000003;
    
    int t1[N], t2[N], c[N];
    void st(int *x, int *y, int *sa, int n, int m) {
    	int i;
    	for(i = 0; i < m; ++i) c[i] = 0;
    	for(i = 0; i < n; ++i) ++c[x[y[i]]];
    	for(i = 1; i < m; ++i) c[i] += c[i - 1];
    	for(i = n - 1; i >= 0; --i) sa[--c[x[y[i]]]] = y[i];
    }
    void mkhz(int *a, int *sa, int n, int m) {
    	int i, j, p, *x = t1, *y = t2, *t;
    	for(i = 0; i < n; ++i) x[i] = a[i], y[i] = i;
    	st(x, y, sa, n, m);
    	for(j = 1, p = 1; p < n; j <<= 1, m = p) {
    		for(i = n - j, p = 0; i < n; ++i) y[p++] = i;
    		for(i = 0; i < n; ++i) if (sa[i] >= j) y[p++] = sa[i] - j;
    		st(x, y, sa, n, m);
    		for(t = x, x = y, y = t, x[sa[0]] = 0, p = 1, i = 1; i < n; ++i)
    			x[sa[i]] = y[sa[i]] == y[sa[i - 1]] && y[sa[i] + j] == y[sa[i - 1] + j] ? p - 1 : p++;
    	}	
    }
    void mkh(int *r, int *sa, int *rank, int *h, int n) {
    	int k = 0, i, j;
    	for(i = 1; i <= n; ++i) rank[sa[i]] = i;
    	for(i = 1; i <= n; h[rank[i++]] = k)
    		for(k ? --k : 0, j = sa[rank[i] - 1]; r[i + k] == r[j + k]; ++k);
    }
    
    char s[N];
    int a[N], sa[N], rank[N], h[N], n, minn[N];
    void mkmin() {
    	int pos = rank[1]; minn[pos] = h[pos];
    	for(int i = pos; i > 1; --i)
    		minn[i - 1] = min(minn[i], h[i]);
    	for(int i = pos + 1; i <= n; ++i)
    		minn[i] = min(minn[i - 1], h[i]);
    }
    void Qhz() {
    	int sq = sqrt((double)n);
    	for(int i = 1; i <= sq; ++i)
    		if (n % i == 0 && minn[rank[1 + i]] == n - i)
    			{printf("%d
    ", n / i); return;}
    	puts("1");
    }
    int main() {
    	while (scanf("%s", s + 1), s[1] != '.') {
    		n = strlen(s + 1);
    		for(int i = 1; i <= n; ++i)
    			a[i] = s[i];
    		mkhz(a, sa, n + 1, 256);
    		mkh(a, sa, rank, h, n);
    		mkmin();
    		Qhz();
    	}
    	return 0;
    }
    

    呜呜呜~

  • 相关阅读:
    如何使用robots.txt及其详解
    有序列表
    前端开发大众手册(包括工具、网址、经验等)
    转载:Tim O'Reilly与John Battelle谈即将开幕的Web
    转载:iframe全跨域高度自适应解决方案
    javascript 学习笔记
    【C#文件夹锁】C#文件夹加锁小工具
    Pro Silverlight 5 in C# 分享
    在Winform窗体中使用WPF控件(附源码)
    【C#文件锁】C#加密解密文件小工具
  • 原文地址:https://www.cnblogs.com/abclzr/p/5417103.html
Copyright © 2011-2022 走看看