Problem(M34):Abc Strings

本文深入探讨了AI音视频处理领域中的关键技术,特别是视频分割与语义识别。通过详细解释这些技术的工作原理、应用案例及实际效果,旨在为读者提供全面的理解和洞察。

Judge Info

  • Memory Limit: 65537KB
  • Case Time Limit: 2000MS
  • Time Limit: 2000MS
  • Judger: Normal

Description

Let’s define a kind of string of length N which only consists of characters ‘.’, ‘a’, ‘b’, ‘c’. Character ‘.’ must be replaced by ‘a’, ‘b’ or ‘c’. You are asked to count the number of ways to modify such kind of string such that for any ‘b’ in the string , the adjacent character on its right is not a ‘a’ and for any ‘c’ in the string, the adjacent character on its right is not a ‘b’. For example, “aabc” is valid, and “bac”, “acb” are invalid.

Input

The first line is a number T(1<=T<=20) which indicates the number of test cases. For each test case there is a number N(1<=N<=100000) which indicates the length of the string and the following line is the input string.

Output

If the string contains ‘.’ and is impossible to construct such kind of string or the string itself is invalid, output “NO”,else print the number of all valid strings mod 1000,000,007.

Sample Input

2
3
..b
4
.ba.

Sample Output

4
NO


#include <iostream>


#include <cstdio>
#include <cstring>
#include <string.h>
#include <algorithm>


#define mod 1000000007;




#include <map>
using namespace std; 
char f[100005];


int dp[100005][3];    //与前一位的状态有关
int vis[100005][3];  //可能的状态


int main()
{

int i,j,t,n;
scanf("%d",&t);
for (i=1;i<=t;i++)
{
memset(dp,0,sizeof(dp));
memset(vis,0,sizeof(vis));


scanf("%d",&n);
scanf("%s",f);

if (f[0]=='a')
{
dp[0][0]=1;
vis[0][0]=1;
}
if (f[0]=='b')
{
dp[0][1]=1;
vis[0][1]=1;
}
if (f[0]=='c')
{
dp[0][2]=1;
vis[0][2]=1;
}
if (f[0]=='.')
{
dp[0][0]=1;
vis[0][0]=1;
dp[0][1]=1;
vis[0][1]=1;
dp[0][2]=1;
vis[0][2]=1;
}

for (j=1;j<n;j++)
{
if (f[j]=='a'||f[j]=='.')
{
if (vis[j-1][0])
{
dp[j][0]=(dp[j][0]+dp[j-1][0])%mod;
vis[j][0]=1;
}
if (vis[j-1][2])
{
dp[j][0]=(dp[j][0]+dp[j-1][2])%mod;
vis[j][0]=1;
}

}
if (f[j]=='b'||f[j]=='.')
{
if (vis[j-1][0])
{
dp[j][1]=(dp[j][1]+dp[j-1][0])%mod;
vis[j][1]=1;
}
if (vis[j-1][1])
{
dp[j][1]=(dp[j][1]+dp[j-1][1])%mod;
vis[j][1]=1;
}

}
if (f[j]=='c'||f[j]=='.')
{
if (vis[j-1][0])
{
dp[j][2]=(dp[j][2]+dp[j-1][0])%mod;
vis[j][2]=1;
}
if (vis[j-1][1])
{
dp[j][2]=(dp[j][2]+dp[j-1][1])%mod;
vis[j][2]=1;
}

if (vis[j-1][2])
{
dp[j][2]=(dp[j][2]+dp[j-1][2])%mod;
vis[j][2]=1;
}

}
}
int k;
int ok=0;
        for(k=0;k<3;k++)
if(vis[n-1][k])
ok=1;
        if(ok==0){
            printf("NO\n");
        }
else
{
int ans=0;
for(k=0;k<3;k++) 
{
ans+=dp[n-1][k];
ans%=mod;
}
printf("%d\n",ans);
}

}







return 0;
}








节省空间算法
利用滚动数组和 last
/*
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define mod 1000000007
char f[100005];
int dp[2][4]; 
int main()
{
int i,j,t;
scanf("%d",&t);
for (i=1;i<=t;i++)
{
memset(dp,0,sizeof(dp)); 
 
int n;
scanf("%d",&n);
scanf("%s",f);
 
int flag=0;
char last=f[0];
for (j=1;j<n;j++)
{
if (last=='b'  && f[j]=='a' || last=='c'&&f[j]=='b'  )
{
printf("NO\n");
flag=1;
break;
}
else
last=f[j]; 
}
if (flag) continue;
 
if (f[0]=='.')
{
dp[0][0]=1;
dp[0][1]=1;
dp[0][2]=1;
}
if (f[0]=='a')
dp[0][0]=1;
if (f[0]=='b')
dp[0][1]=1;
if (f[0]=='c')
dp[0][2]=1;
 
 
 
last=f[0]; 
 
for (j=1;j<n;j++)
{
 
if (f[j]=='a')
{
if ( last=='a')
dp[j%2][0]=(dp[((j-1)%2)][0])%mod;
 
if ( last=='c')
dp[j%2][0]=(dp[((j-1)%2)][2])%mod;
 
if (last=='.')
dp[j%2][0]=(dp[((j-1)%2)][0]+dp[((j-1)%2)][2])%mod;
 
 
}
 
if (f[j]=='b')
{
if (last=='a')
dp[j%2][1]=(dp[((j-1)%2)][0])%mod;
 
if (last=='b')
dp[j%2][1]=(dp[((j-1)%2)][1])%mod;
 
if (last=='.')
dp[j%2][1]=(dp[((j-1)%2)][1]+dp[((j-1)%2)][0])%mod;
 
}
 
if (f[j]=='c')
{
if (last=='a')
dp[j%2][2]=(dp[((j-1)%2)][0])%mod;
 
if (last=='b')
dp[j%2][2]=(dp[(j-1)%2][1])%mod;
 
if (last=='c')
dp[j%2][2]=(dp[(j-1)%2][2])%mod;
 
if (last=='.')
{
dp[j%2][2]=(dp[j%2][2]+dp[(j-1)%2][0])%mod;
 
dp[j%2][2]=(dp[j%2][2]+dp[(j-1)%2][1])%mod;
 
dp[j%2][2]=(dp[j%2][2]+dp[(j-1)%2][2])%mod;
}
 
 
}
 
if (f[j]=='.')
{
if (last=='a')
{
dp[j%2][0]=(dp[(j-1)%2][0])%mod;
dp[j%2][1]=(dp[(j-1)%2][0])%mod;
dp[j%2][2]=(dp[(j-1)%2][0])%mod;
 
 
}
if (last=='b')
{
dp[j%2][1]=(dp[(j-1)%2][1])%mod;
dp[j%2][2]=(dp[(j-1)%2][1])%mod;
 
}
if (last=='.')
{
dp[j%2][0]=(dp[j%2][0]+dp[(j-1)%2][0])%mod;
dp[j%2][1]=(dp[j%2][1]+dp[(j-1)%2][0])%mod;
dp[j%2][2]=(dp[j%2][2]+dp[(j-1)%2][0])%mod;
dp[j%2][1]=(dp[j%2][1]+dp[(j-1)%2][1])%mod;
dp[j%2][2]=(dp[j%2][2]+dp[(j-1)%2][1])%mod;
dp[j%2][0]=(dp[j%2][0]+dp[(j-1)%2][2])%mod;
dp[j%2][2]=(dp[j%2][2]+dp[(j-1)%2][2])%mod;
}
if (last=='c')
{
dp[j%2][0]=(dp[(j-1)%2][2])%mod;
dp[j%2][2]=(dp[(j-1)%2][2])%mod;
 
}
 
}
last=f[j];
dp[(j-1)%2][0]=0;
dp[(j-1)%2][1]=0;
dp[(j-1)%2][2]=0;
dp[(j-1)%2][3]=0;
}
 
 
 
if (n%2==1)

{int   ans=0,k;
for(k=0;k<3;k++) 
{
ans+=dp[0][k];
ans%=mod;
}
printf("%d\n",ans); 
 
}
else
{
int   ans=0,k;
for(k=0;k<3;k++) 
{
ans+=dp[1][k];
ans%=mod;
}
printf("%d\n",ans); 
 


}


}
return 0;
}
*/

# P3370 【模板】字符串哈希 ## 题目描述 如题,给定 $N$ 个字符串(第 $i$ 个字符串长度为 $M_i$,字符串内包含数字、大小写字母,大小写敏感),请求出 $N$ 个字符串中共有多少个不同的字符串。 **友情提醒:如果真的想好好练习哈希的话,请自觉。** ## 输入格式 第一行包含一个整数 $N$,为字符串的个数。 接下来 $N$ 行每行包含一个字符串,为所提供的字符串。 ## 输出格式 输出包含一行,包含一个整数,为不同的字符串个数。 ## 输入输出样例 #1 ### 输入 #1 ``` 5 abc aaaa abc abcc 12345 ``` ### 输出 #1 ``` 4 ``` ## 说明/提示 ### 数据范围 对于 $30\%$ 的数据:$N\leq 10$,$M_i≈6$,$M_{\max}\leq 15$。 对于 $70\%$ 的数据:$N\leq 1000$,$M_i≈100$,$M_{\max}\leq 150$。 对于 $100\%$ 的数据:$N\leq 10000$,$M_i≈1000$,$M_{\max}\leq 1500$。 ### 样例说明 样例中第一个字符串 $\tt{abc}$ 和第三个字符串 $\tt{abc}$ 是一样的,所以所提供字符串的集合为 $\{\tt{aaaa},\tt{abc},\tt{abcc},\tt{12345}\}$,故共计 $4$ 个不同的字符串。 ### 拓展阅读 以下的一些试题从不同层面体现出了字符串哈希算法的正确性分析。 - [P12197 Hash Killer I](https://www.luogu.com.cn/problem/P12197) - [P12198 Hash Killer II](https://www.luogu.com.cn/problem/P12198) - [P12199 (目前无解)Hash Killer III](https://www.luogu.com.cn/problem/P12199) - [P12200 Hash Killer Extra](https://www.luogu.com.cn/problem/P12200) - [P12201 Hash Killer Phantasm](https://www.luogu.com.cn/problem/P12201) - [P7350 「MCOI-04」Dream and Strings](https://www.luogu.com.cn/problem/P7350) #include <iostream> #include <cstring> using ull = unsigned long long; using namespace std; const int MAXN = 1e5+10; const int base = 33967; int n; ull f[MAXN],p[MAXN]; char s[MAXN]; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin>>s+1; int n=strlen(s+1); p[0]=1; for(int i=1;i<=n;i++) { f[i]=f[i-1]*base+s[i]; p[i]=p[i-1]*base; } int l,r; cin>>l>>r; ull hash_val=f[r]-f[l-1]*p[r-l+1]; cout<<hash_val; return 0; }帮我补全代码
07-13
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值