ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题解 字符消除2

2021-08-20 08:02:05  阅读:215  来源: 互联网

标签:字符 int 题解 boarder long ull siz 消除 define


传送门

首先证一个结论:t集合即是原串的boarder不用证了吧

于是转化题意:要构造一个boarder集合确定的01串
考虑从小的boarder推向大的boarder,令小boarder为s,大boarder为t

  1. \(|s|*2 \leqslant |t|\) 此时在s后面补上s的一段后缀即可
  2. \(|s|*2 > |t|\) 把原串复制一遍接在最后,其它位置全补0
    kmp check一下它有没有多出来新的boarder,如果有就把补的最后一个0换成1

证明见这里

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 200010
#define ll long long
#define ull unsigned long long
//#define int long long 

int n;
char s[N];
ull h[N], p[N];
const ull base=131;
inline ull hashing(ull* h, int l, int r) {return h[r]-h[l-1]*p[r-l+1];}

namespace force{
	int t[2000], top;
	ull h2[2010];
	void solve() {
		//cout<<"solve "<<n<<endl;
		top=0;
		for (int i=1; i<=n; ++i) h[i]=h[i-1]*base+s[i];
		for (int i=1; i<=n; ++i) {
			ull m=hashing(h, 1, i);
			int j;
			for (j=i+1; j+i-1<=n; j+=i) 
				if (hashing(h, j, j+i-1)!=m) goto jump;
			if (j<=n && hashing(h, 1, n-j+1)!=hashing(h, j, n)) goto jump;
			t[++top]=i;
			jump: ;
		}
		//cout<<"top: "<<top<<endl;
		//for (int i=1; i<=top; ++i) cout<<t[i]<<' '; cout<<endl;
		int lim=1<<n;
		for (int s=0; s<lim; ++s) {
			//cout<<"now s="<<bitset<6>(s)<<endl;
			int pos=1;
			for (int i=1; i<=n; ++i) h2[i]=h2[i-1]*base+(s&(1<<(i-1))?1:0);
			for (int i=1; i<=n; ++i) {
				ull m=hashing(h2, 1, i);
				int j;
				for (j=i+1; j+i-1<=n; j+=i) 
					if (hashing(h2, j, j+i-1)!=m) goto jump2;
				if (j<=n && hashing(h2, 1, n-j+1)!=hashing(h2, j, n)) goto jump2;
				//cout<<"cmp: "<<i<<' '<<t[pos]<<endl;
				if (i==t[pos]) ++pos;
				else break;
				jump2: ;
			}
			if (pos==top+1) {
				for (int i=n-1; ~i; --i) printf("%d", s&(1<<i)?1:0); printf("\n");
				break;
			}
		}
	}
}

namespace task{
	int nxt[N], t[N], top, siz;
	char ans[N];
	void solve() {
		top=0;
		nxt[1]=0;
		for (int i=2,j=0; i<=n; ++i) {
			while (j && s[i]!=s[j+1]) j=nxt[j];
			if (s[i]==s[j+1]) ++j;
			nxt[i]=j;
		}
		int it=n;
		do {t[++top]=it; it=nxt[it];} while (it) ;
		//cout<<"nxt: "; for (int i=1; i<=top; ++i) cout<<t[i]<<' '; cout<<endl;
		siz=0;
		if (t[top]==1) ans[++siz]=0;
		else {
			while (t[top]>1) ans[++siz]=0, --t[top];
			ans[++siz]=1;
		}
		for (int i=top-1; i; --i) {
			//cout<<"i: "<<i<<' '<<siz<<endl;
			//cout<<"ans: "; for (int i=1; i<=siz; ++i) printf("%d", ans[i]); printf("\n");
			if (siz*2>=t[i]) 
				for (int j=siz-(t[i]-siz)+1,ends=siz; j<=ends; ++j) ans[++siz]=ans[j];
			else {
				//cout<<"pos1"<<endl;
				int dlt=t[i]-siz+1;
				for (int j=siz+1; j<dlt; ++j) ans[j]=0;
				for (int j=dlt; j<=t[i]; ++j) ans[j]=ans[j-dlt+1];
				nxt[1]=0;
				for (int k=2,j=0; k<=t[i]; ++k) {
					while (j && ans[k]!=ans[j+1]) j=nxt[j];
					if (ans[k]==ans[j+1]) ++j;
					nxt[k]=j;
				}
				if (nxt[t[i]]!=siz) ans[dlt-1]=1;
				siz=t[i];
			}
		}
		for (int i=1; i<=siz; ++i) printf("%d", ans[i]); printf("\n");
	}
}

signed main()
{
	int T;
	
	//cout<<double(sizeof(h)*3)/1024/1024<<endl;
	p[0]=1;
	for (int i=1; i<=2000; ++i) p[i]=p[i-1]*base;
	scanf("%d", &T);
	while (T--) {
		scanf("%s", s+1);
		n=strlen(s+1);
		//force::solve();
		task::solve();
	}
	
	return 0;
}

标签:字符,int,题解,boarder,long,ull,siz,消除,define
来源: https://www.cnblogs.com/narration/p/15164802.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有