Tokitsukaze, CSL and Palindrome Game
阿新 • • 發佈:2020-08-16
1001 Tokitsukaze, CSL and Palindrome Game
比較字典序的時候考慮樹上倍增,用樹上倍增的時候要保證路徑相同,所以把路徑雜湊一下,直接比較即可
但是當我把maxn
開到1e5+5的時候很奇怪的就wa了,開到1e5+20才過
// Created by CAD #include <bits/stdc++.h> #define ll long long using namespace std; const int maxn=1e5+20; const int base=233; int lg[maxn]; ll b[maxn]; namespace pam{ int sz,tot,last; const int chr_siz=26; int len[maxn],fail[maxn],state[maxn],f[maxn][30],dep[maxn]; char s[maxn]; int Next[maxn][chr_siz]; vector<int> g[maxn]; ll Hash[maxn]; int node(int l){ len[++sz]=l; fail[sz] =0; return sz; } void init(){ for(int i=0;i<=sz;++i){ len[i]=fail[i]=state[i]=dep[i]=Hash[i]=0,g[i].clear(); for(int j=0;j<chr_siz;++j) Next[i][j]=0; for(int j=0;j<30;++j) f[i][j]=0; } for(int i=0;i<=tot;++i) s[i]=' '; sz=-1; s[tot=0]='$'; node(0),node(-1); fail[0]=1,last=0; } int getfail(int x){ while(s[tot-len[x]-1]!=s[tot]) x=fail[x]; return x; } void insert(char c){ s[++tot]=c; int now=getfail(last); if(!Next[now][c-'a']){ int id=node(len[now]+2); fail[id]=Next[getfail(fail[now])][c-'a']; Next[now][c-'a']=id; } last=Next[now][c-'a']; state[tot]=last; } void dfs(int x,int fa){ if(~fa) Hash[x]=Hash[fa]*base+len[x]; f[x][0]=fa,dep[x]=dep[fa]+1; for(int i=1;i<=lg[dep[x]];++i) f[x][i]=f[f[x][i-1]][i-1]; for(auto i:g[x]) if(i!=fa) dfs(i,x); } void solve_init(){ //建樹 for(int i=1;i<=sz;++i) g[fail[i]].push_back(i); dfs(0,-1); } ll hash(int l,int r){ //求出路徑的雜湊值 return Hash[r]-Hash[f[l][0]]*b[dep[r]-dep[l]+1]; } int get(int x,int length){ //找到起始狀態 if(len[x]==length) return x; for(int k=lg[dep[x]]-1;k>=0;--k) if(len[f[x][k]]>length) x=f[x][k]; return f[x][0]; } int judge(int a,int b){ //倍增法比較字典序 if(len[a]>len[b]) return 1; else if(len[b]>len[a]) return -1; for(int k=lg[dep[a]]-1;k>=0;--k) if(len[f[a][k]]==len[f[b][k]]&&hash(f[a][k],a)==hash(f[b][k],b)) a=f[a][k],b=f[b][k]; a=f[a][0],b=f[b][0]; if(len[a]>len[b]) return 1; else if(len[b]>len[a]) return -1; else return 0; } int solve(int l1,int r1,int l2,int r2){ int a=get(state[r1],r1-l1+1),b=get(state[r2],r2-l2+1); return -judge(a,b); } } char s[maxn]; int main() { int t;scanf("%d",&t); b[0]=1; for(int i=1;i<=1e5+2;++i) lg[i]=lg[i-1]+(1<<lg[i-1]==i),b[i]=b[i-1]*base; while(t--){ int n;scanf("%d%s",&n,s); pam::init(); for(int i=0;i<n;++i) pam::insert(s[i]); pam::solve_init(); int q;scanf("%d",&q); while(q--){ int l1,l2,r1,r2;scanf("%d%d%d%d",&l1,&r1,&l2,&r2); int flag=pam::solve(l1,r1,l2,r2); if(flag==1) puts("sjfnb"); else if(flag==-1) puts("cslnb"); else puts("draw"); } } return 0; }