hdu 6096 String
题
OvO http://acm.hdu.edu.cn/showproblem.php?pid=6096
( 2017 Multi-University Training Contest - Team 6 - 1001)
解
对于n个串,构造新串。(构造方法:例如若串为ABCDE,构造新串为AEBDCCDBEA)、
将新串插入到字典树(字典树每个节点存放一个vector)中,对于每个新串遍历到的节点,将原串的长度长度放入这些节点的vector中、
将字典树每个节点的vector从小到大排序。
对于询问的前后缀,类似地构造新串,空余出补*,(例如前缀ABC,后缀DEFGH,构造新串为AHBGCF*E*D)
然后对于这些新串在字典树中进行询问,对于每个匹配到的节点,合法串的数量就是vector中保存的长度大于等于前缀后缀长度和的数字的数量。
(思路来源于某大佬)
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <queue> using namespace std; const int M=5e5+44; const int N=1e5+44; struct Node { int len,pos; }; queue<Node> que; struct Trie { const static int TRIE_M=1204000; const static int CHAR_SIZE=26; int root,tol,ch[TRIE_M][27]; vector<int> tree[TRIE_M]; int newnode() { tree[tol].clear(); for(int i=0;i<26;i++) ch[tol][i]=-1; return tol++; } void init() { tol=0; root=newnode(); } void insert(char strtmp[],int lentmp) { // cout<<"strtmp: "<<strtmp<<endl; int i,j; int now=root,nxt,valtmp; for(i=0;i<lentmp;i++) { valtmp=strtmp[i]-'a'; if(ch[now][valtmp]==-1) ch[now][valtmp]=newnode(); now=ch[now][valtmp]; tree[now].push_back(lentmp/2); // cout<<"now: "<<now<<" tree[now] size: "<<tree[now].size()<<endl; } } void build() { for(int i=0;i<tol;i++) sort(tree[i].begin(),tree[i].end()); } int getval(int pos,int xlen) { int li=-1,ri=tree[pos].size(),mid; // cout<<"getval pos:"<<pos<<' '<<" size: "<<tree[pos].size()<<endl; // cout<<"detail val:"<<tree[pos][0]<<' '<<tree[pos][1]<<endl; while(li<ri-1) { mid=(li+ri)>>1; if(tree[pos][mid]<xlen) li=mid; else ri=mid; } // cout<<"li: "<<li<<endl; return tree[pos].size()-(li+1); } int query(char strtmp[],int lentmp,int xlen) { char chrtmp; int i,j,ret=0,pos,nxt; Node q,qq; while(!que.empty()) que.pop(); q.len=0; q.pos=0; que.push(q); while(!que.empty()) { q=que.front(); que.pop(); chrtmp=strtmp[q.len]; pos=q.pos; // cout<<chrtmp<<' '<<pos; // if(chrtmp!='*') // cout<<" ch[pos][chrtmp-'a']= "<<ch[pos][chrtmp-'a']; // cout<<endl; if(chrtmp=='*') for(i=0;i<26;i++) { nxt=ch[pos][i]; if(nxt!=-1) { qq.len=q.len+1; qq.pos=nxt; if(qq.len==lentmp) ret+=getval(qq.pos,xlen); else que.push(qq); } } else { nxt=ch[pos][chrtmp-'a']; if(nxt!=-1) { qq.len=q.len+1; qq.pos=nxt; if(qq.len==lentmp) ret+=getval(qq.pos,xlen); else que.push(qq); } } } return ret; } } trie; int n,q; char strtmp[M],pretmp[M],suftmp[M],strget[M]; int main() { // freopen("数据\\1001.in","r",stdin); // freopen("数据\\fxxl1001.out","w",stdout); int lentmp,prelen,suflen; int cas,i,j,ans; scanf("%d",&cas); while(cas--) { scanf("%d%d",&n,&q); trie.init(); for(i=1;i<=n;i++) { scanf("%s",strtmp); lentmp=strlen(strtmp); for(j=0;j<lentmp;j++) { strget[j*2]=strtmp[j]; strget[j*2+1]=strtmp[lentmp-1-j]; } trie.insert(strget,lentmp*2); } trie.build(); for(i=1;i<=q;i++) { scanf("%s%s",pretmp,suftmp); reverse(suftmp,suftmp+strlen(suftmp)); prelen=strlen(pretmp); suflen=strlen(suftmp); lentmp=max(prelen,suflen); for(j=0;j<lentmp;j++) { if(j<prelen) strget[j*2]=pretmp[j]; else strget[j*2]='*'; if(j<suflen) strget[j*2+1]=suftmp[j]; else strget[j*2+1]='*'; } lentmp*=2; if(strget[lentmp-1]=='*') lentmp--; ans=trie.query(strget,lentmp,prelen+suflen); printf("%d\n",ans); } } return 0; } /* 1 4 1 aaaa aaaaa aaaaa aa aa aa */