《算法周周练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

 

posted @ 2020-07-08 08:51  levill  阅读(122)  评论(0编辑  收藏  举报