• Tinkoff Internship Warmup Round 2018 and Codeforces Round #475 (Div. 1) D. Frequency of String


    https://codeforces.com/problemset/problem/963/D

    length distnct

    number <= sqrt(1e5)=316

    所有串t出现次数<=1e5*315

    对于某个串t出现的位置 递增

    ac自动机一个点唯一指向另外一个点

    记录需要合并的子孙下标,该节点已有的位置

    对于目标点,对数组进行合并。

    详见代码

      1 #include <cstdio>
      2 #include <cstdlib>
      3 #include <cmath>
      4 #include <cstring>
      5 #include <string>
      6 #include <algorithm>
      7 #include <iostream>
      8 using namespace std;
      9 #define ll long long
     10 #include <vector>
     11 
     12 const double eps=1e-8;
     13 const ll inf=1e9;
     14 const ll mod=1e9+7;
     15 const int maxn=1e5+10;
     16 const int maxm=sqrt(100)+10;
     17 
     18 /**
     19 all string are distinct
     20 **/
     21 
     22 struct node
     23 {
     24     int num,ind;
     25     node *nex[26],*pre,*fail;
     26 }*tr,*be,*pos,*p,*td,*q[maxn];
     27 
     28 char s[maxn],str[maxn];
     29 int least[maxn],re[maxn];
     30 int head1,tail1,d1,q1[maxn],cnt_least;
     31 
     32 vector<int> hap[maxn],son[maxn],temp,temp1;
     33 ///son:记录有用的子孙节点的编号,只有处于目标点时才合并
     34 
     35 void arr_merge(int ind)
     36 {
     37     temp1.clear();
     38     vector<int>::iterator i=temp.begin(),j=hap[ind].begin(),i_end=temp.end(),j_end=hap[ind].end();
     39     while (i!=i_end && j!=j_end)
     40     {
     41         if (*i < *j)
     42             temp1.push_back(*i),i++;
     43         else
     44             temp1.push_back(*j),j++;
     45     }
     46     while (i!=i_end)
     47         temp1.push_back(*i),i++;
     48     while (j!=j_end)
     49         temp1.push_back(*j),j++;
     50     temp=temp1;
     51 }
     52 
     53 int main()
     54 {
     55     int n,N,len,i,d,head,tail,ind,num,ii,jj;
     56     vector<int>::iterator j;
     57     tr=new node();
     58     be=new node();
     59     tr->pre=be;
     60     tr->fail=be;
     61     be->fail=be;
     62     for (i=0;i<26;i++)
     63         be->nex[i]=tr;
     64 
     65     scanf("%s",s);
     66     scanf("%d",&n);
     67     for (N=1;N<=n;N++)
     68     {
     69         scanf("%d%s",&least[N],str);
     70         len=strlen(str);
     71         re[N]=strlen(str);
     72         pos=tr;
     73         for (i=0;i<len;i++)
     74         {
     75             d=str[i]-97;
     76             if (!pos->nex[d])
     77             {
     78                 p=new node();
     79                 pos->nex[d]=p;
     80                 p->pre=pos;
     81             }
     82             pos=pos->nex[d];
     83         }
     84         pos->num=N;
     85     }
     86 
     87     head=0,tail=1;
     88     q[1]=tr;
     89     while (head<tail)
     90     {
     91         head++;
     92         td=q[head];
     93         for (d=0;d<26;d++)
     94             if (td->nex[d])
     95             {
     96                 pos=td->fail;
     97                 while (!pos->nex[d])
     98                     pos=pos->fail;
     99                 td->nex[d]->fail=pos->nex[d];
    100                 q[++tail]=td->nex[d];
    101                 td->nex[d]->ind=tail;///
    102             }
    103     }
    104 
    105     len=strlen(s);
    106     pos=tr;
    107     for (i=0;i<len;i++)
    108     {
    109         d=s[i]-97;
    110         while (!pos->nex[d])
    111             pos=pos->fail;
    112         pos=pos->nex[d];
    113 
    114         hap[pos->ind].push_back(i);
    115     }
    116 
    117     for (i=tail;i>=1;i--)
    118     {
    119         pos=q[i];
    120         ind=pos->ind;
    121         num=pos->num;
    122         if (num)
    123         {
    124             temp.clear();
    125             head1=0,tail1=1;
    126             q1[1]=ind;
    127             while (head1<tail1)
    128             {
    129                 head1++;
    130                 d1=q1[head1];
    131                 if (!hap[d1].empty())
    132                 {
    133                     if (temp.empty())
    134                         temp=hap[d1];
    135                     else
    136                         arr_merge(d1);
    137                 }
    138                 for (j=son[d1].begin();j!=son[d1].end();j++)
    139                     q1[++tail1]=*j;
    140             }
    141             hap[ind]=temp;
    142             son[ind].clear();
    143 
    144             cnt_least=inf;
    145 //            printf("size =%d
    ",hap[ind].size());
    146             jj=hap[ind].size()-least[num];
    147             for (ii=0;ii<=jj;ii++)
    148                 cnt_least=min(cnt_least,hap[ind][ii+least[num]-1]-hap[ind][ii]);
    149             if (cnt_least==inf)
    150                 re[num]=-1;
    151             else
    152                 re[num]+=cnt_least;
    153         }
    154         if (!hap[ind].empty() || !son[ind].empty())
    155             son[pos->fail->ind].push_back(ind);
    156     }
    157 
    158     for (i=1;i<=n;i++)
    159         printf("%d
    ",re[i]);
    160     return 0;
    161 }

    bitset方法

    https://codeforces.com/contest/963/submission/37784765

    代码中

    记录文本串s某个字符的所有位置

    在模式串中对于一个字符t[i],b[t[i]-'a']为所有可以对应的位置,左移i个单位;如果对于所有j,tmp某个位置都为1,则tmp该个位置为1,模式串t可以与s+j匹配。

    时间复杂度O(length(s)*sum(length(t))

  • 相关阅读:
    try,catch,finally的简单问题
    设置类可序列化,写入VIewState
    jQuery实现购物车物品数量的加减 (针对GirdView的类似事件)
    js获取Gridview中的控件id
    asmx ASp.net AJAX使用 ScriptManager
    js返回上一页并刷新,JS实现关闭当前子窗口,刷新父窗口
    asp.net(c#)网页跳转七种方法小结
    在触发器中回滚和提交
    redis 缓存对象、列表
    spring cloud 停止服务
  • 原文地址:https://www.cnblogs.com/cmyg/p/11111467.html
Copyright © 2020-2023  润新知