zoukankan      html  css  js  c++  java
  • 《算法周周练14》

    E:

    首先看到公共前后缀。

    可以想到kmp的next数组就是求得最长公共前后缀。

    那么假定的最长公共前后缀就是next[len].

    如果这个串中有和它一样长的。那就说明这个最长公共前后缀在字符串中间出现过。

    怎么判断?用next数组,当next数组合next[len]时,说明就是最长公共前后缀。

    为了不和前后缀重合,从第二个位置开始查找next数组,到倒数第二个位置。

    当这个串中没有和最长公共前后缀一样的字符串时。答案就是前缀的最长公共前后缀。

    首先对于前缀的最长公共前后缀,肯定在字符串中出现过。

    因为前缀的后缀是属于串中。

    那么为什么答案就是他?因为对于前后缀。

    如果还要保证公共相同。那么显然就是最长的他们本身的前后缀。

    因为他们本身是正序对应的。

    Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 1e5+5;
    const int M = 1e6+5;
    const LL Mod = 1e18;
    #define pi acos(-1)
    #define INF 1e8
    #define INM INT_MIN
    #define pb(a)  push_back(a)
    #define mk(a,b) make_pair(a,b)
    #define dbg(x) cout << "now this num is " << x << endl;
    #define met0(axx) memset(axx,0,sizeof(axx));
    #define metf(axx) memset(axx,-1,sizeof(axx));
    #define sd(ax) scanf("%d",&ax)
    #define sld(ax) scanf("%lld",&ax)
    #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
    #define sdd(ax,bx) scanf("%d %d",&ax,&bx)
    #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
    #define sfd(ax) scanf("%lf",&ax)
    #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
    #define pr(a) printf("%d\n",a)
    #define plr(a) printf("%lld\n",a)
    int nxt[N];
    void slove(string t)
    {
        nxt[0] = -1;
        int k = -1,i = 0,len = t.size();
        while(i < len)
        {
            if(k == -1 || t[i] == t[k]) nxt[++i] = ++k;
            else k = nxt[k];
        }
    }
    void run()
    {
        string s;cin >> s;
        slove(s);
        int len = s.size();
        int ma = nxt[len],mx = -1;
        for(int i = 1;i < len-1;++i)
        {
            if(nxt[i+1] == ma) {mx = ma;break;}
        }
        if(mx == -1) mx = nxt[ma];
        for(int i = 0;i < mx;++i) printf("%c",s[i]);
        printf("\n");
    }
    int main()
    {
        run();
        system("pause");
        return 0;
    }
    View Code

    C:

    思路:换根dp.

    首先考虑对于根时,它的情况数就是

    ans = (dp[son1]+1)*(dp[son2]+1)*(dp[son3]+1)*....

    可以发现就是所有儿子的情况向下的情况数乘积。

    但是对于儿子节点,还存在向上的情况数。所以考虑换根后的影响。

    对于son,它的方案数就是它上面的 * 它下面的。

    那么对于它下面的就是dp[son].对于它上面的方案数。

    可以从fa转移。

    观察ans可知。son上面的就是f[son] = ans[fa]/(dp[son]+1).

    那么这时ans[son] = dp[son]*(f[son]+1); // 这里将f也看成一个分支,所以要加1.

    但是这题,可能会出现dp[u]+1 % Mod = 0的情况。这时父节点的值将为0.

    但是对于这题,为0的情况应该看成不存在来处理。

    这时,就跳过这条边,重新统计父节点的向下情况数。

    然后用 f[fa] * dp[fa].//父节点向下的 *( 父节点向上的+1).

     Code:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    typedef pair<LL,int> pii;
    const int N = 1e6+5;
    const int M = 1e6+5;
    const int Mod = 1e9+7;
    #define pi acos(-1)
    #define INF 1e8
    #define INM INT_MIN
    #define pb(a)  push_back(a)
    #define mk(a,b) make_pair(a,b)
    #define dbg(x) cout << "now this num is " << x << endl;
    #define met0(axx) memset(axx,0,sizeof(axx));
    #define metf(axx) memset(axx,-1,sizeof(axx));
    #define sd(ax) scanf("%d",&ax)
    #define sld(ax) scanf("%lld",&ax)
    #define sldd(ax,bx) scanf("%lld %lld",&ax,&bx)
    #define sdd(ax,bx) scanf("%d %d",&ax,&bx)
    #define sddd(ax,bx,cx) scanf("%d %d %d",&ax,&bx,&cx)
    #define sfd(ax) scanf("%lf",&ax)
    #define sfdd(ax,bx) scanf("%lf %lf",&ax,&bx)
    #define pr(a) printf("%d\n",a)
    #define plr(a) printf("%lld\n",a)
    LL dp[N],f[N],ans[N],fa[N];
    vector<int> G[N];
    inline int read()
    {
        int x = 0,f = 1;char c = getchar();
        while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();}
        while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();}
        return x*f;
    }
    LL quick_mi(LL a,LL b)
    {
        LL re = 1;
        while(b)
        {
            if(b&1) re = (re*a)%Mod;
            a = (a*a)%Mod;
            b >>= 1;
        }
        return re;
    }
    LL inv(LL n){return quick_mi(n,Mod-2)%Mod;}
    void dfs(int u,int ffa)
    {
        dp[u] = 1;
        fa[u] = ffa;
        for(auto v : G[u])
        {
            if(v == ffa) continue;
            dfs(v,u);
            dp[u] = dp[u]*(dp[v]+1)%Mod;
        }
    }
    void dfs1(int u)
    {
        if(fa[u] != 0)
        {
            LL tmp;
            if((dp[u]+1)%Mod == 0)
            {
                tmp = f[fa[u]]+1;
                for(auto e : G[fa[u]])
                {
                    if(e == u || e == fa[fa[u]]) continue;
                    tmp = tmp*(dp[e]+1)%Mod;
                }
            }
            else tmp = ans[fa[u]]*inv(dp[u]+1)%Mod;
            f[u] = tmp;ans[u] = dp[u]*(tmp+1)%Mod;
        }
        for(auto v : G[u]) if(v != fa[u]) dfs1(v);
    }
    void run()
    {
        int n;n = read();
        for(int i = 1;i < n;++i)
        {
            int u,v;sdd(u,v);
            G[u].pb(v),G[v].pb(u);
        }
        dfs(1,0);
        ans[1] = dp[1];
        dfs1(1);
        for(int i = 1;i <= n;++i) plr(ans[i]);
    }
    int main()
    {
        run();
        system("pause");
        return 0;
    }
    View Code
  • 相关阅读:
    php中file_get_contents的图片乱码
    Lsh and Rsh (左移和右移)
    |=的含义
    Intercultural Communication Drama
    VS代码块快速折叠快捷键
    C++sqrt()函数与sqrtf()函数的区别
    C++中union和struct之间的区别
    泛型编程
    生成百度网盘目录文件
    字符串前L的含义
  • 原文地址:https://www.cnblogs.com/zwjzwj/p/13264864.html
Copyright © 2011-2022 走看看