BZOJ4236: JOIOJI
Aug 18, 2015 08:11:53 PM
题解:
考虑任意一个串都是两个前缀之差.
如果这个串要满足$num(J)=num(O)=num(I)$,那么两个前缀$num(J),num(O),num(I)$的相对大小关系必须是相同的.
我们对于每个前缀记下$num(J)-num(O),num(J)-num(I)$,然后利用map随便搞搞就行了.
代码:
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
typedef pair<int,int> pii;
#define mp make_pair
#define N 200010
char s[N];
map<pii,int>M;
int main(){
int n;
scanf("%d",&n);
scanf("%s",s+1);
M[mp(0,0)]=0;
int J=0,O=0,I=0,ans=0;
for(int i=1;i<=n;++i){
if(s[i]=='J')
++J;
if(s[i]=='O')
++O;
if(s[i]=='I')
++I;
if(M.count(mp(J-O,J-I)))
ans=max(ans,i-M[mp(J-O,J-I)]);
else
M[mp(J-O,J-I)]=i;
}
cout<<ans<<endl;
return 0;
}
BZOJ2882:工艺 STL+后缀自动机
Feb 02, 2015 03:04:02 PM
思路:这大概也算是后缀自动机裸题了吧.
虽然最小表示法最靠谱,不过我还是懒,于是用map水了一发.好方便啊~`
注意数据范围有一些不靠谱,详情见代码= =
#include<cstdio>
#include<cstring>
#include<cctype>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
#define N 500010
map<int,int>tranc[N<<1];int pa[N<<1],len[N<<1],cnt,root,last;
inline int newnode(int l){
len[++cnt]=l;return cnt;
}
inline void init(){
root=last=newnode(0);
}
int a[N<<1];
int main(){
int n;scanf("%d",&n);register int i,j;for(i=1;i<=n;++i)scanf("%d",&a[i]),a[i+n]=a[i];
int p,np,q,nq,y;
for(init(),i=1;i<=n*2;++i){
np=newnode(len[last]+1);
for(p=last,y=a[i];tranc[p].find(y)==tranc[p].end();p=pa[p])tranc[p][y]=np;
if(!p)pa[np]=root;
else{
q=tranc[p][y];
if(len[q]==len[p]+1)pa[np]=q;
else{
nq=newnode(len[p]+1),pa[nq]=pa[q],pa[q]=pa[np]=nq;
tranc[nq]=tranc[q];
for(;p&&tranc[p].find(y)!=tranc[p].end()&&tranc[p][y]==q;p=pa[p])tranc[p][y]=nq;
}
}last=np;
}
map<int,int>::iterator it;
for(i=1,p=root;i<=n;++i){
if(i>1)putchar(' ');
it=tranc[p].begin();
printf("%d",it->first);
p=tranc[p][it->first];
}
return 0;
}