zoukankan      html  css  js  c++  java
  • 刷题总结——字符串(ssoj)

    题目:

    给定n个小的字符串T和一个大的字符串S,先输出T总共再S中出现了多少次

    然后q个询问···每次修改S上的一个字母,然后再次输出上述答案···

    n小于1000,q<200000,T的总长度和S的长度都小于100000;

    题解:

    我们可以发现,每次修改位置P,那么S影响的范围只有在P-MAX到P+MAX的范围,其中MAX为T的最长长度····所以将这一范围的S跑一边AC自动机··然后更新答案即可··

    这道题也让我发现我做AC自动机以来一直有的一个不好的习惯··每次求出现次数都是暴力跳fail指针,这样再这道题里直接T····

    其实再我们bfs构建fail指针时,设u的指针为v,我们可以直接tree[u].cnt+=tree[v].cnt,这样每次加的时候直接加上一个节点cnt就可以了··不用暴力跳fail···代码:

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cmath>
    #include<ctime>
    #include<cctype>
    #include<cstring>
    #include<string>
    #include<algorithm>
    #include<queue>
    using namespace std;
    queue<int>que;
    const int N=100005;
    struct node
    {
      int son[26],cnt,fail;
      void clear()
      {
        memset(son,0,sizeof(son));
        cnt=fail=0;
      }
    }tree[N];
    int n,m,T,tot,maxx=0;
    char s[N],t[5];
    inline int R()
    {
      char c;int f=0;
      for(c=getchar();c<'0'||c>'9';c=getchar());
      for(;c<='9'&&c>='0';c=getchar())  f=(f<<3)+(f<<1)+c-'0';  
      return f;
    }
    int buf[1024];
    inline void W(int x){
        if(!x){putchar('0');return ;}
        if(x<0){putchar('-');x=-x;}
        while(x) buf[++buf[0]]=x%10,x/=10;
        while(buf[0]) putchar(buf[buf[0]--]+48);
        return ;
    }
    
    inline void build()
    {
      int po=1;
      int len=strlen(s);maxx=max(maxx,len);
      for(int i=0;i<len;i++)
      {
        if(!tree[po].son[s[i]-'a'])
          tree[tree[po].son[s[i]-'a']=++tot].clear();
        po=tree[po].son[s[i]-'a'];
      }
      tree[po].cnt++;
    }
    inline void buildfail()
    {
      que.push(1);
      while(!que.empty())
      {
        int u=que.front();que.pop();
        for(int i=0;i<26;i++)
        {
          int v=tree[u].fail;
          while(!tree[v].son[i])  v=tree[v].fail;
          v=tree[v].son[i];int w=tree[u].son[i];
          if(w)  tree[w].fail=v,que.push(w),tree[w].cnt+=tree[v].cnt; 
          else tree[u].son[i]=v;
        }
      }
    }
    int main()
    {
      //freopen("string.in","r",stdin);
      //freopen("string.out","w",stdout);
      n=R(),m=R();
      for(int i=0;i<26;i++)
        tree[0].son[i]=1;
      tree[tot=1].clear();
      for(int i=1;i<=n;i++)
      {
        scanf("%s",s);   
        build();
      }
      buildfail();
      scanf("%s",s);
      int len=strlen(s),a;
      int now=1,ans=0;
      for(int i=0;i<len;i++)
      {
        now=tree[now].son[s[i]-'a'];
        ans+=tree[now].cnt;
      }
      W(ans),putchar('
    ');
      while(m--)
      {  
          a=R();scanf("%s",t);
        int now=1,ans1=0,ans2=0;
        for(int i=max(0,a-maxx);i<=min(a+maxx-1,len-1);i++)
        {
          now=tree[now].son[s[i]-'a'];                   
          ans1+=tree[now].cnt;
        }
        ans-=ans1;
        s[a-1]=t[0];now=1;
        for(int i=max(0,a-maxx);i<=min(a+maxx-1,len-1);i++)
        {
          now=tree[now].son[s[i]-'a'];
          ans2+=tree[now].cnt;
        }
        ans+=ans2;
        W(ans),putchar('
    ');
      }
      return 0;
    }
  • 相关阅读:
    HDU
    纯C++去雾算法
    拓扑排序
    SG 函数初步 HDU 1536 &amp;&amp; HDU 1944
    <html>
    XML制作RSS源
    ACM退役前2个月总结
    javascript 的 jasmine 的測试语句
    Vue.js父与子组件之间传参
    $.contents().find设置的data在iframe子页面无法获取值
  • 原文地址:https://www.cnblogs.com/AseanA/p/7677782.html
Copyright © 2011-2022 走看看