5RE求调
查看原帖
5RE求调
749301
AmiyaCast楼主2024/1/16 17:29

自己de了一天,现在的结果是,可以确定后缀排序后有的rk重复了,数据点4的第3个数据排完后rk[1] = rk[4] = 26,但是我一直每整明白为什么,请dalao指教!这是那个数据点:

10
vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv
dvdvdvdvdvdvdvdvdvdvdvdvdv
jhyjhyjhyjhyjhyjhyjhyjhyjhy
dkbjdkbjdkbjdkbjdkbjdkbjdkbjdkbj
ezlbtezlbtezlbtezlbtezlbtezlbtezlbtezlbt
efwduoefwduoefwduoefwduoefwduoefwduoefwduo
eqgdlgxeqgdlgxeqgdlgxeqgdlgxeqgdlgxeqgdlgx
mwuoqleamwuoqleamwuoqleamwuoqlea
gwcbhodfpgwcbhodfpgwcbhodfpgwcbhodfp
vprveevprveevprveevprvee

而且神奇的是,我只要把第三个串和第四个串的顺序换一下,就不会RE,而且甚至答案还是对的

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<vector>
#include<map>
#include<queue>
#include<algorithm>
#define ll long long
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define per(i,a,b) for(int i=b;i>=a;--i)
using namespace std;
inline double fread(){
	double t; scanf("%lf", &t); return t;
}
inline ll read()
{ 
    ll x=0,f=1;
    char c=getchar();
    while (c<'0' || c>'9')
    {
        if (c=='-')  f=-1;
        c=getchar();
    }
    while (c>='0' && c<='9')
    {
        x=x*10+c-'0';
         c=getchar();
    }
    return x*f;
}

inline void print(ll x)
{
	if(x < 0) putchar('-'), x = -x;
	if(x > 9) print(x / 10);
	putchar(x % 10 + '0');
	return ;
}
inline void pprint(ll x)
{
	print(x); puts("");
}

inline void cprint(char *s, ll x)
{
	printf("%s: %d\n", s, x);
}

inline void kprint(ll x)
{
	print(x); putchar(' ');
}

inline void fpprint(double x){
	printf("%lf\n", x);
}

inline void fkprint(double x){
	printf("%lf ", x);
}

const int N = 5e4 + 7;
int rk[N << 1], sa[N], n, lstrk[N << 1], lstsa[N], w, m = 127, cnt[N], h[N], f1[N][20], f2[N][20], beg[N], ed[N], lrk[N << 1];
char s[N];

#define siz n * sizeof(int)

void init(){
	memset(cnt, 0, sizeof cnt);
	memset(sa, 0, sizeof sa);
	memset(rk, 0, sizeof rk);
	memset(h, 0, sizeof h);
	m = 200;//init在这个地方! 
//	printf("%s\n", s + 1);
	for(int i = 1; i <= n; ++i) ++cnt[rk[i] = s[i]];
	for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
	for(int i = n; i >= 1; --i) sa[cnt[rk[i]]--] = i;
	memcpy(lstrk + 1, rk + 1, siz);
	for(int p = 0, i = 1; i <= n; ++i)
		if(lstrk[sa[i]] == lstrk[sa[i - 1]])
			rk[sa[i]] = p;
		else
			rk[sa[i]] = ++p;
			
	
	for(w = 1; w < n; w <<= 1, m = n){
		for(int p = 0, i = n; i >= n - w + 1; --i) lstsa[++p] = i;
		for(int p = w, i = 1; i <= n; ++i)
			if(sa[i] > w)  lstsa[++p] = sa[i] - w; 
		memset(cnt, 0, sizeof cnt);
		for(int i = 1; i <= n; ++i) ++cnt[rk[lstsa[i]]];
		for(int i = 1; i <= m; ++i) cnt[i] += cnt[i - 1];
		for(int i = n; i >= 1; --i) sa[cnt[rk[lstsa[i]]]--] = lstsa[i];
		memcpy(lstrk + 1, rk + 1, siz);
		for(int p = 0, i = 1; i <= n; ++i)
			if(lstrk[sa[i]] == lstrk[sa[i - 1]] && lstrk[sa[i] + w] == lstrk[sa[i - 1] + w])
				rk[sa[i]] = p;
			else
				rk[sa[i]] = ++p;
	}
//	rk[sa[n]] = n;
	for(int i = 1, k = 0; i <= n; ++i){
		if(rk[i] == 0) continue;
		if(k) --k;
		while(s[i + k] == s[sa[rk[i] - 1] + k]) ++k;
		h[rk[i]] = k;
	}
	
}

void init1(){
	memset(f1, 0x7f, sizeof f1);
	for(int i = 1; i <= n; ++i)
		f1[i][0] = h[i];
	for(int j = 1; (1 << j) <= n; ++j)
		for(int i = 1; i <= n; ++i)
			f1[i][j] = min(f1[i][j - 1], f1[i + (1 << (j - 1))][j - 1]);
}

void init2(){
	memset(f2, 0x7f, sizeof f2);

	for(int i = 1; i <= n; ++i)
		f2[i][0] = h[i];
	for(int j = 1; (1 << j) <= n; ++j)
		for(int i = 1; i <= n; ++i)
			f2[i][j] = min(f2[i][j - 1], f2[i + (1 << (j - 1))][j - 1]);
}

int lcp(int x, int y){
	if(x > y) swap(x, y);
	x++;
	int k;
	k = log2(y - x + 1);
	return min(f1[x][k], f1[y - (1 << k) + 1][k]);
}

int lcs(int x, int y){
	if(x > y) swap(x, y);
	x ++;
	int k;
	k = log2(y - x + 1);
	return min(f2[x][k], f2[y - (1 << k) + 1][k]);
}

//区间修改
void ch(int *a, int st, int wid){
	a[st]++;
	a[st + wid]--; 
}

int main(){
	int T = read();
	while(T--){
		memset(beg, 0, sizeof beg);
		memset(ed, 0, sizeof ed);
		
		scanf("%s", s + 1);
		n = strlen(s + 1);
		init();
		init1();
//		cout << "complete 1" << endl;
		
		reverse(&s[1], &s[n + 1]);
//		for(int i = 1; i <= n / 2; ++i)
//			swap(s[i], s[n - i + 1]);
//		printf("%s\n", s + 1);
		
		memcpy(lrk + 1, rk + 1, siz);
		init();
		init2();
//		cout << "complete 2" << endl;
		
//		cout << "check:" << lcp(4, 6) << endl;
//		cout << lrk[1] << " " << lrk[2] << endl;
//		cout << lcp(1, 2) << endl;
		
		for(int len = 1; len <= n / 2; ++len){
//			cout << len << endl;
			for(int j = 1; (j + 1) * len <= n; ++j){
				int l = j * len, r = (j + 1) * len;
				int pre = min(len, lcs(rk[n - r + 1], rk[n - l + 1]));
				int nxt = min(len, lcp(lrk[l], lrk[r]));
				if(pre + nxt < len + 1) continue;
				int prel = l - pre + 1, edr = r + nxt - 1;
				int wid = (l + nxt - 1) - (r - pre + 1) + 1 + 1;
				beg[prel]++; beg[prel + wid]--;
				ed[edr + 1]--; ed[edr - wid + 1]++;
			}
		}
		for(int i = 1; i <= n; ++i)
			beg[i] += beg[i - 1];
		for(int i = 1; i <= n; ++i)  
			ed[i] += ed[i - 1];
		
//		for(int i = 1; i <= n; ++i)
//			cout << beg[i] << " "; puts("");
//		for(int i = 1; i <= n; ++i)
//			cout << ed[i] << " "; puts("");
//		cout << "!" << endl;
		ll ans = 0;
		for(int i = 1; i < n; ++i){
			ans += ed[i] * beg[i + 1];
		}
//		puts("ans = ");
		pprint(ans);
	}
	return 0;
}
2024/1/16 17:29
加载中...