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