Codeforces 451D Count Good Substring 规律+DP
2017-07-10 16:54
369 查看
题意:当融合s中连续相同字符后,s'为回文 则s合法 例如"aabba" 融合后 "aba"
给出string s,只包含字符a,b,|s|<=1e5,问s有多少个长度为偶/奇数的合法子串?
方法1:
设dp[i][0/1] 以i结尾,长度为偶/奇数的合法子串个数.
明显s[i]=s[i-1]时, dp[i][0]=dp[i-1][1]
因为只有'a','b'两种字符 最后a结尾的回文肯定为 a,aba,ababa,abababa
当s[i]!=s[i-1]时 形式为XXXba
找到'a'字符前一个'a'出现位置 pre[i]结尾有多少个回文,i也有多少个(i能和其融合变回文)
则dp[i][0]+=dp[pre[i]][(i-pre[i])%2?1:0]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+20;
const ll mod=1e9+7;
ll n,m,pre
;
ll dp
[2];
string s;
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
while(cin>>s)
{
ll pa=-1,pb=-1;
memset(dp,0,sizeof(dp));
for(int i=0;s[i];i++)
{
if(s[i]=='a')
pre[i]=pa,pa=i;
else
pre[i]=pb,pb=i;
}
for(int i=0;s[i];i++)
{
dp[i][1]=1;
if(pre[i]==-1)
continue;
int len=i-pre[i];
dp[i][0]+=dp[pre[i]][len%2?1:0];
dp[i][1]+=dp[pre[i]][len%2?0:1];
}
ll odd=0,even=0;
for(int i=0;s[i];i++)
odd+=dp[i][1],even+=dp[i][0];
cout<<even<<' '<<odd<<endl;
}
return 0;
}
方法2:只要头尾两个下标对应字符相等,融合后的string 肯定为回文
i.e:a..b 中间任意,融合后只能为bab -> ababa
若当前结尾下标为奇数,前面偶数位置有多少个,(odd-even+1)长度为偶数的就有多少个,其余情况类似..
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-10;
const int inf=0x3f3f3f3f;
const int N=2e5+20;
char s
;
int main()
{
while(scanf("%s",s+1)!=EOF)
{
ll pa=0,pb=0,qa=0,qb=0;
ll odd=0,even=0;
for(int i=1;s[i];i++)
{
if(i%2)
{
if(s[i]=='a')
pa++,even+=qa,odd+=pa;
else
pb++,even+=qb,odd+=pb;
}
else
{
if(s[i]=='a')
qa++,even+=pa,odd+=qa;
else
qb++,even+=pb,odd+=qb;
//cout<<qb<<' '<<endl;
}
}
cout<<even<<' '<<odd<<endl;
}
return 0;
}
给出string s,只包含字符a,b,|s|<=1e5,问s有多少个长度为偶/奇数的合法子串?
方法1:
设dp[i][0/1] 以i结尾,长度为偶/奇数的合法子串个数.
明显s[i]=s[i-1]时, dp[i][0]=dp[i-1][1]
因为只有'a','b'两种字符 最后a结尾的回文肯定为 a,aba,ababa,abababa
当s[i]!=s[i-1]时 形式为XXXba
找到'a'字符前一个'a'出现位置 pre[i]结尾有多少个回文,i也有多少个(i能和其融合变回文)
则dp[i][0]+=dp[pre[i]][(i-pre[i])%2?1:0]
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+20;
const ll mod=1e9+7;
ll n,m,pre
;
ll dp
[2];
string s;
int main()
{
cin.tie(0);
ios::sync_with_stdio(false);
while(cin>>s)
{
ll pa=-1,pb=-1;
memset(dp,0,sizeof(dp));
for(int i=0;s[i];i++)
{
if(s[i]=='a')
pre[i]=pa,pa=i;
else
pre[i]=pb,pb=i;
}
for(int i=0;s[i];i++)
{
dp[i][1]=1;
if(pre[i]==-1)
continue;
int len=i-pre[i];
dp[i][0]+=dp[pre[i]][len%2?1:0];
dp[i][1]+=dp[pre[i]][len%2?0:1];
}
ll odd=0,even=0;
for(int i=0;s[i];i++)
odd+=dp[i][1],even+=dp[i][0];
cout<<even<<' '<<odd<<endl;
}
return 0;
}
方法2:只要头尾两个下标对应字符相等,融合后的string 肯定为回文
i.e:a..b 中间任意,融合后只能为bab -> ababa
若当前结尾下标为奇数,前面偶数位置有多少个,(odd-even+1)长度为偶数的就有多少个,其余情况类似..
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const double eps=1e-10;
const int inf=0x3f3f3f3f;
const int N=2e5+20;
char s
;
int main()
{
while(scanf("%s",s+1)!=EOF)
{
ll pa=0,pb=0,qa=0,qb=0;
ll odd=0,even=0;
for(int i=1;s[i];i++)
{
if(i%2)
{
if(s[i]=='a')
pa++,even+=qa,odd+=pa;
else
pb++,even+=qb,odd+=pb;
}
else
{
if(s[i]=='a')
qa++,even+=pa,odd+=qa;
else
qb++,even+=pb,odd+=qb;
//cout<<qb<<' '<<endl;
}
}
cout<<even<<' '<<odd<<endl;
}
return 0;
}
相关文章推荐
- CodeForces 474D--规律dp
- Codeforces 474D Flowers (线性dp 找规律)
- CodeForces 294B Shaass and Bookshelf 【规律 & 模拟】或【Dp】
- codeforces 603A. Alternative Thinking(数学找规律 或者 dp)
- Codeforces_841_C Leha and Function(贪心+构造|规律)
- CodeForces 219D 树形DP
- codeforces 55D 数位DP
- codeforces 392 B. Tower of Hanoi(汉诺塔 DP)
- [CodeForces 615B]Longtail Hedgehog[DP]
- CodeForces 156 C.Cipher(dp)
- Codeforces 707 C. Pythagorean Triples(找规律)——Codeforces Round #368 (Div. 2)
- CodeForces 213 B.Numbers(组合数学+dp)
- codeforces 159D D. Palindrome pairs( manacher+dp )
- Codeforces 118D Caesar's Legions【dp】好题
- CodeForces 623 B.Array GCD(数论+dp)
- Codeforces 622C Not Equal on a Segment 【线段树 Or DP】
- 【DP】CodeForces 148D
- [Codeforces 176B] Word Cut (脑洞+KMP+dp)
- CodeForces 478D Red-Green Towers (DP)
- Codeforces-840C On the Bench(dp)