zoukankan      html  css  js  c++  java
  • NOIP 模拟 929

    匹配

    有两个字符串A,B,其中B是A的一个长度为$l_{B}$前缀,现在给B末尾填上字符,求A的最大前缀等于B的后缀

    $T<=10,l_{B}<=100000,l_{B}<=l_{A}<=2*l_{B}$,所有字母均为小写字母

    题解

    考虑到B除了最后一个字符就是A的前缀,所以如果变换后的B不是A的前缀,那么求B的最大前缀等于后缀即可。

    用kmp就行了

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn=200005;
    int T,lena,lenb;
    char c[2],s[maxn],t[maxn];
    int fail[maxn];
    void kmp(){
        fail[0]=fail[1]=0;
        for(int i=1;i<lenb;i++){
            int t=fail[i];
            while(t&&s[i]!=s[t]) t=fail[t];
            fail[i+1]=(s[i]==s[t] ? t+1 : 0);
        }
    }
    
    int main(){
        freopen("string.in","r",stdin);
        freopen("string.out","w",stdout);
        scanf("%d",&T);
        while(T--){
            scanf("%d%d%s%s",&lena,&lenb,s,c);
            if(s[lenb]==c[0]) {printf("%d
    ",lenb+1);continue;}
            s[lenb++]=c[0];
            kmp();
            printf("%d
    ",fail[lenb]);
        }
    }
    string

    回家

    有一个n个点m条边的图,求从1到n的必经点。

    m<=2n,n<=200000,多组数据

    题解

    给一种错误思路:考虑必经点一定是割点,必经点一定在最短路上。所以tarjan求出割点之后,跑两遍bfs求最短路,最后判断。

    为什么会错呢?因为这些只是性质,并不能推出结论。

    最主要的就是不能保证这个割点能使1和n不连通

    所以考虑在tarjan的时候记录n是否在子树中,判断即可。

    细节在代码注释

    #include<queue>
    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    using namespace std;
    
    const int maxn=200005;
    const int inf=0x3f3f3f;
    int t,n,m,cur,cnt;
    int head[maxn];
    int dfn[maxn],low[maxn];
    int top,sta[maxn];
    bool cut[maxn],con[maxn];
    int dis[maxn][2];
    struct edge{
        int x,y,next;
    }e[maxn<<3];
    
    template<class T>inline void read(T &x){
        x=0;int f=0;char ch=getchar();
        while(!isdigit(ch)) {f|=(ch=='-');ch=getchar();}
        while(isdigit(ch)) {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
        x = f ? -x : x ;
    }
    
    void add(int x,int y){
        e[++cnt]=(edge){x,y,head[x]};
        head[x]=cnt;
    }
    
    void init(){
        cnt=top=cur=0;
        memset(cut,false,sizeof(cut));
        memset(con,false,sizeof(con));
        memset(head,0,sizeof(head));
        memset(dfn,0,sizeof(dfn));
        memset(low,0,sizeof(low));
        for(int i=1;i<=n;i++)
         dis[i][0]=dis[i][1]=inf;
    }
    
    void tarjan(int x,int fa){
        int num=0;if(x==n) con[x]=true;
        low[x]=dfn[x]=++cur;
        for(int i=head[x];i;i=e[i].next){
            int y=e[i].y;
            if(!dfn[y]){
                tarjan(y,x);
                low[x]=min(low[x],low[y]);
                con[x]|=con[y];
                if(dfn[x]<=low[y]&&con[y])//判断con[y]:当因为dfn[x]<=low[y]知道是割点的时候会y的子树分开,如果最后判断x会造成分开的子树不含n 
                  cut[x]=true;
            }
            else if(y!=fa)  low[x]=min(low[x],dfn[y]);
        }
    }
    
    void solve(){
        read(n);read(m);
        init();
        for(int i=1;i<=m;i++){
            int x,y;
            read(x);read(y);
            if(x==y) continue;
            add(x,y);add(y,x);
        }
        tarjan(1,0);
        for(int i=2;i<n;i++)
         if(cut[i])
          sta[++top]=i;
        printf("%d
    ",top);
        for(int i=1;i<=top;i++)
         printf("%d ",sta[i]);
        putchar(10);
    }
    
    int main(){
        freopen("home.in","r",stdin);
        freopen("home.out","w",stdout);
        read(t);
        while(t--)solve();
    }
    /*
    2 
    4 3
    1 2
    2 3
    3 4
    5 5
    1 2
    2 3
    3 4
    4 5
    4 1
    */
    home

  • 相关阅读:
    2020杭电HDU-6831多校第六场Fragrant numbers(区间DP打表)
    Gym 102219H-Are You Safe?(凸包求解+判断点与凸包关系)
    2020杭电HDU-6827多校第六场Road To The 3rd Building(找规律求期望)
    洛谷P1099&Noip 2007提高-树网的核(树直径上的尺取)
    2020杭电HDU-6832多校第六场A Very Easy Graph Problem(最短路转最小生成树+dfs)
    CodeForces 950D-A Leapfrog in the Array(打表找规律)
    使用odoo价格表[pricelist]对价格进行特别处理,如 .99
    odoo 10 生产自动领料
    安装odoo服务
    advanced validation on purchase.
  • 原文地址:https://www.cnblogs.com/sto324/p/11620730.html
Copyright © 2011-2022 走看看