P3167 [CQOI2014]通配符匹配
阿新 • • 發佈:2019-03-01
mem turn return har ash for oss -h amp
吐槽
本來是去寫AC自動機的,然後發現數據範圍每個串100000,有100個串(???),連塞進trie樹裏都塞不進去,玩個鬼的AC自動機啊,tag不要亂打啊
最後拿字符串hash+爆搜一發搜過去了。。。
思路
挺惡心的搜索吧
考慮分段,按?號和*號分段,對於每段內的hash判斷是否一致,*號和?號按題意處理即可
然後邊界不要寫掛就好了
代碼
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int base=131; int xing[100100],wen[100100],n,lens,cntx,cntw,lent; unsigned long long hashs1[100100],hashs2[100100],pow[100100]; char s[100100],t[100100]; void init(void){ pow[0]=1; for(int i=1;i<=100001;i++) pow[i]=pow[i-1]*base; } unsigned long long hash1(int l,int r){ return hashs1[r]-hashs1[l-1]*pow[r-l+1]; } unsigned long long hash2(int l,int r){ return hashs2[r]-hashs2[l-1]*pow[r-l+1]; } bool dfs(int poss,int post){ // printf("%d %d\n",poss,post); if(poss==lens+1&&post==lent+1){ return true; } else if(poss==lens+1||post==lent+1) return false; if(s[poss]=='*'){ for(int i=post;i<=lent+1;i++) if(dfs(poss+1,i)) return true; return false; } else if(s[poss]=='?'){ return dfs(poss+1,post+1); } else{ int tx=lower_bound(xing+1,xing+cntx+1,poss)-(xing),tw=lower_bound(wen+1,wen+cntw+1,poss)-(wen); // printf("tx=%d tw=%d\n",tx,tw); // printf("compare 1(%d,%d) 2(%d,%d) :\n",poss,min(xing[tx],wen[tw])-1,post,post+min(xing[tx],wen[tw])-poss-1); if(hash1(poss,min(xing[tx],wen[tw])-1)==hash2(post,post+(min(xing[tx],wen[tw])-poss-1))){ // printf("true\n"); return dfs(min(xing[tx],wen[tw]),post+(min(xing[tx],wen[tw])-poss)); } else { // printf("false\n"); return false; } } } int main(){ init(); scanf("%s",s+1); lens=strlen(s+1); for(int i=1;i<=lens;i++){ if(s[i]!='*'||s[i]!='?') hashs1[i]=hashs1[i-1]*base+s[i]; if(s[i]=='*') xing[++cntx]=i; if(s[i]=='?') wen[++cntw]=i; } xing[++cntx]=lens+1; wen[++cntw]=lens+1; scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%s",t+1); lent=strlen(t+1); memset(hashs2,0,sizeof(hashs2)); for(int j=1;j<=lent;j++){ hashs2[j]=hashs2[j-1]*base+t[j]; } printf("%s\n",dfs(1,1)?"YES":"NO"); } return 0; }
P3167 [CQOI2014]通配符匹配