POJ - 2406 Power Strings(DC3算法)

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.

題意: 給出一個字符串, 詢問該串最多由幾個循環串組成

思路:

我們可以發現當一個串由長度爲i的子串循環組成時

1: rank[0] = rank[i] + 1

2: len % i == 0

3: heig[rak[0]] == len - i

對於第一點當前串如果是由該串循環組成, 則第一個字符開始的循環串一定與第i個字符開始的循環串排名相鄰

所以 rank[0] = rank[i] + 1

對於第二點長度必定整除纔行

第三點

顯然第一個字符開始的循環串跟上一個排名的循環串的LCP = len - i

這個差值i即是循環串的長度

例如ababab

ababab與abab 的LCP = 4 = 6 - 2

PS:這題求SA使用倍增算法, 您將會得到

所以使用DC3吧, 不過這DC3我也看不懂, 也不會改(網上偷份拿着用吧), 下標從0開始輸入的串可真是難受

//#include <bits/stdc++.h>
#include <time.h>
#include <string>
#include <stdlib.h>
#include <algorithm>
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <functional>
#include <set>
#include <map>
#include <queue>
//#include <unordered_map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;

#ifdef LOCAL
#define debug(x) cout << "[" __FUNCTION__ ": " #x " = " << (x) << "]\n"
#define TIME cout << "RuningTime: " << clock() << "ms\n", 0
#else
#define TIME 0
#endif
#define hash_ 1000000009
#define Continue(x) { x; continue; }
#define Return(x) { x; return; }
#define Break(x) { x; break; }
const int mod = 1e9 + 7;
const int N = 3e6 + 10;
const int INF = 0x3f3f3f3f;
const ll LINF = 0x3f3f3f3f3f3f3f3f;
#define gc p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1000000, stdin), p1 == p2) ? EOF : *p1++;
inline int read(){ static char buf[1000000], *p1 = buf, *p2 = buf; register int x = false; register char ch = gc; register bool sgn = false; while (ch != '-' && (ch < '0' || ch > '9')) ch = gc; if (ch == '-') sgn = true, ch = gc; while (ch >= '0'&& ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = gc; return sgn ? -x : x; }
ll fpow(ll a, int b, int mod) { ll res = 1; for (; b > 0; b >>= 1) { if (b & 1) res = res * a % mod; a = a * a % mod; } return res; }
#define F(x) ((x)/3+((x)%3==1?0:tb))
#define G(x) ((x)<tb?(x)*3+1:((x)-tb)*3+2)
int len;
char s[N];
int sa[N], rak[N], heig[N], r[N], wa[N], wb[N], wv[N], wws[N];
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++) wws[i] = 0;
	for (i = 0; i < n; i++) wws[wv[i]]++;
	for (i = 1; i < m; i++) wws[i] += wws[i - 1];
	for (i = n - 1; i >= 0; i--) b[--wws[wv[i]]] = a[i];
	return;
}
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 dc3(int *r, int *sa, int n, int m){
	int i, j, *rn = r + n, *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++];
	return;
}
void calheight(int *r, int *sa, int n)
{
	int i, j, k = 0;
	for (i = 1; i <= n; ++i) rak[sa[i]] = i;
	for (i = 0; i < n; heig[rak[i++]] = k)
		for (k ? k-- : 0, j = sa[rak[i] - 1]; r[i + k] == r[j + k]; ++k);
	return;
}
void solve()
{
	for (int i = 1; i <= len; i++)
	{
		if (len % i == 0 && rak[0] == rak[i] + 1 && heig[rak[0]] == len - i)
			Return(cout << len / i << endl)
	}
	cout << "1" << endl;
	return ;
}
int main()
{
#ifdef LOCAL
	freopen("D:/input.txt", "r", stdin);
#endif
	while (~scanf("%s", s))
	{
		if (!strcmp(s, "."))
			break;
		len = strlen(s);
		for (int i = 0; i < len; i++)
			r[i] = s[i];
		r[len] = 0;
		dc3(r, sa, len + 1, 200);
		calheight(r, sa, len);
		solve();
	}
	return TIME;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章