Advertisement
osipyonok

Substring searching o(|substring|)

Nov 1st, 2016
116
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.56 KB | None | 0 0
  1. #include<bits/stdc++.h>
  2.  
  3. #define INF 1000010000
  4. #define nl '\n'
  5. #define pb push_back
  6. #define ppb pop_back
  7. #define mp make_pair
  8. #define fi first
  9. #define se second
  10. #define pii pair<int,int>
  11. #define pdd pair<double,double>
  12. #define all(c) (c).begin(), (c).end()
  13. #define SORT(c) sort(all(c))
  14. #define sz(c) (c).size()
  15. #define rep(i,n) for( int i = 0; i < n; ++i )
  16. #define repi(i,n) for( int i = 1 ; i <= n; ++i )
  17. #define repn(i,n) for( int i = n - 1 ; i >= 0 ; --i )
  18. #define repf(j,i,n) for( int j = i ; j < n ; ++j )
  19. #define die(s) {std::cout << s << nl;}
  20. #define dier(s) {std::cout << s; return 0;}
  21. #define vi vector<int>
  22. typedef long long ll;
  23.  
  24. using namespace std;
  25.  
  26. string str;
  27.  
  28. struct SuffixLink{
  29.     int start;
  30.     int end;
  31.     int to;
  32.     public:
  33.     SuffixLink(){
  34.         to = -1;
  35.     }
  36.     SuffixLink(int s , int e , int t){
  37.         start = s;
  38.         end = e;
  39.         to = t;
  40.     }
  41. };
  42.  
  43. struct Node{
  44.     int suffix;
  45.     vector<SuffixLink> links;
  46.     public:
  47.     Node(){
  48.         suffix = -1;
  49.         links = vector<SuffixLink>(256 , SuffixLink());
  50.     }
  51. };
  52.  
  53. vector<Node> tree;
  54. int root , temp;
  55.  
  56. inline int newNode(){
  57.     tree.pb(Node());
  58.     return sz(tree) - 1;
  59. }
  60.  
  61. inline int t(int e){
  62.     return (e < 0 ? -e - 1 : str[e]);
  63. }
  64.  
  65. inline void link(int from , int start , int end , int to){
  66.     tree[from].links[t(start)] = SuffixLink(start , end , to);
  67. }
  68.  
  69. inline int &f(int v){
  70.     return tree[v].suffix;
  71. }
  72.  
  73. void initTree(){
  74.     tree.clear();
  75.     temp = newNode();
  76.     root = newNode();
  77.    
  78.     f(root) = temp;
  79.     rep(i , 256){
  80.         link(temp , -i - 1 , -i , root);
  81.     }
  82. }
  83.  
  84. pii canonize(int v , int start , int end){
  85.     if(start >= end){
  86.         return {v , start};
  87.     }
  88.     SuffixLink cur = tree[v].links[t(start)];
  89.     while(end - start >= cur.end - cur.start){
  90.         start += cur.end - cur.start;
  91.         v = cur.to;
  92.         if(end > start){
  93.             cur = tree[v].links[t(start)];
  94.         }
  95.     }
  96.     return {v , start};
  97. }
  98.  
  99. pii testAndSplit(int v , int start , int end , char ch){
  100.     if(start >= end){
  101.         return {tree[v].links[ch].to != -1 , v};
  102.     }
  103.     SuffixLink cur = tree[v].links[t(start)];
  104.     if(ch == t(cur.start + end - start)){
  105.         return {1 , v};
  106.     }
  107.     int md = newNode();
  108.     link(v , cur.start , cur.start + end - start , md);
  109.     link(md , cur.start + end - start , cur.end , cur.to);
  110.     return {0 , md};
  111. }
  112.  
  113. pii update(int v , int start , int end){
  114.     SuffixLink cur = tree[v].links[t(start)];
  115.     pii splitRes = testAndSplit(v , start , end , t(end));
  116.     int old = root;
  117.     while(splitRes.fi == 0){
  118.         link(splitRes.se , end , INF , newNode());
  119.         if(old != root){
  120.             f(old) = splitRes.se;
  121.         }
  122.         old = splitRes.se;
  123.         pii nwP = canonize(f(v) , start , end);
  124.         v = nwP.fi;
  125.         start = nwP.se;
  126.         splitRes = testAndSplit(v , start , end , t(end));
  127.     }
  128.     if(root != old){
  129.         f(old) = splitRes.se;
  130.     }
  131.     return {v , start};
  132. }
  133.  
  134. inline void Ukkonen(){
  135.     initTree();
  136.     pii act = {root , 0};
  137.     rep(i , sz(str)){
  138.         act = update(act.fi , act.se , i);
  139.         act = canonize(act.fi , act.se , i + 1);
  140.     }
  141. }
  142.  
  143. inline bool IsSubstring(string s){
  144.     int v = root;
  145.     int start = 0;
  146.     int end = 0;
  147.     rep(i , sz(s)){
  148.         char cur = s[i];
  149.         if(end == start){
  150.             if(tree[v].links[cur].to == -1){
  151.                 return 0;
  152.             }
  153.             start = tree[v].links[cur].start;
  154.             end = start + 1;
  155.         }else{
  156.             if(cur != t(end)){
  157.                 return 0;
  158.             }
  159.             ++end;
  160.         }
  161.         if(end == tree[v].links[t(start)].end){
  162.             v = tree[v].links[t(start)].to;
  163.             start = 0;
  164.             end = 0;
  165.         }
  166.     }
  167.     return 1;
  168. }
  169.  
  170. int main() {
  171.     ios_base::sync_with_stdio(false);
  172.     cin.tie(NULL);
  173.     cout.precision(0);
  174.     cin >> str;
  175.     Ukkonen();
  176.     string test;
  177.     while(cin >> test){
  178.         if(IsSubstring(test)){
  179.             die("YES");
  180.         }else{
  181.             die("NO");
  182.         }
  183.     }
  184.     return 0;
  185. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement