zoukankan      html  css  js  c++  java
  • [noi1755]Trie

    定义S对应的数组为$a_{i}=min_{0le j<i,S_{j}=S_{i}}i-j$,特别的,若不存在j,令$a_{i}=i$,那么容易发现存在双射关系就意味这两者对应的数组相同
    因此,考虑需要单词为$a_{i}$,询问串对应的为$b_{i}$,那么如果$b[i,i+l_{a})$与$a$存在双射,当且仅当对于任意j,都有$a_{j}=b_{i+j}vee (a_{j}=jwedge b_{i+j}>j)$
    具体的,使用AC自动机来判断,由于$b_{i+j}>j$的判断,因此要存储当前节点的深度
     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 100005
     4 int V,n,m,l,las[31],d[N],vis[N],nex[N],a[N*5];
     5 char s[N*5];
     6 queue<int>q;
     7 map<int,int>ch[N];
     8 map<int,int>::iterator it;
     9 void hash(){
    10     memset(las,-1,sizeof(las));
    11     for(int i=0;i<l;i++){
    12         a[i]=i-las[s[i]-'A'];
    13         las[s[i]-'A']=i;
    14     }
    15 }
    16 void add(){
    17     int k=0;
    18     for(int i=0;i<l;i++){
    19         if (!ch[k][a[i]])ch[k][a[i]]=++V;
    20         k=ch[k][a[i]];
    21         d[k]=i+1;
    22     }
    23     vis[k]=1;
    24 }
    25 bool query(){
    26     int k=0;
    27     for(int i=0;i<l;i++){
    28         while ((k)&&(!ch[k][min(a[i],d[k]+1)]))k=nex[k];
    29         if (ch[k][min(a[i],d[k]+1)])k=ch[k][min(a[i],d[k]+1)];
    30         if (vis[k])return 1;
    31     }
    32     return 0;
    33 }
    34 void bfs(){
    35     q.push(0);
    36     while (!q.empty()){
    37         int k=q.front();
    38         q.pop();
    39         vis[k]|=vis[nex[k]];
    40         for(it=ch[k].begin();it!=ch[k].end();it++){
    41             int i=nex[k];
    42             while ((i)&&(!ch[i][min((*it).first,d[i]+1)]))i=nex[i];
    43             q.push((*it).second);
    44             if (k)nex[(*it).second]=ch[i][min((*it).first,d[i]+1)];
    45         }
    46     }
    47 }
    48 int main(){
    49     scanf("%d",&n);
    50     for(int i=1;i<=n;i++){
    51         scanf("%s",s);
    52         l=strlen(s);
    53         hash();
    54         add();
    55     }
    56     bfs();
    57     scanf("%d",&m);
    58     for(int i=1;i<=m;i++){
    59         scanf("%s",s);
    60         l=strlen(s);
    61         hash();
    62         if (query())printf("Yes
    ");
    63         else printf("No
    ");
    64     }
    65 }
    View Code
  • 相关阅读:
    FileInputStream 小Demo
    GUI线程 :打字母游戏
    联合线程(案例顾客买蛋糕 :使用join()方法)
    多线程:竞赛
    线程:交通灯
    猜数字游戏
    正则表达式
    音频播放的三种方式:
    进阶篇-用户界面:7.android动画-自定义视图动画
    进阶篇-用户界面:6.android studio使用github开源库实现下拉刷新
  • 原文地址:https://www.cnblogs.com/PYWBKTDA/p/13141631.html
Copyright © 2011-2022 走看看