题解 P1624 【单词缩写】
题目链接:Link
Problem
Solution
考虑到字符串长度只有150,最多20个询问,直接记 $ f(i,j,k)= $ 匹配缩写中前i个字符,最后匹配于第j个有效单词中k号字符的方案数,大力dp即可。
坑点:getline会读入'\r'
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<set>
#include<sstream>
using namespace std;
const int maxn=150;
set<string> emmm;
int n,f[maxn][maxn][maxn];
string t,a,b[maxn];
inline void LOW(string &s)
{
for(int i=0;i<s.size();i++) if('A'<=s[i]&&s[i]<='Z') s[i]=s[i]+32;
}
inline int low(char a) { return 'A'<=a&&a<='Z'?a+32:a; }
int main()
{
#ifdef local
freopen("pro.in","r",stdin);
#endif
cin>>n;
for(int i=0;i<n;i++) { cin>>t; emmm.insert(t); }
getline(cin,t);
while(getline(cin,t))
{
if(t=="LAST CASE"||t=="LAST CASE\r") return 0;
stringstream ss(t);
ss>>a;
a="#"+a;
n=0;
b[++n]="#";
while(ss>>t)
{
LOW(t);
if(emmm.find(t)!=emmm.end()) continue;
n++;
b[n]=t;
}
memset(f,0,sizeof(f));
f[1][1][0]=1;
for(int i=2;i<=a.size();i++)
for(int j=2;j<=n;j++)
for(int k=0;k<b[j].size();k++)
{
if(low(a[i-1])!=b[j][k]) continue;
int &v=f[i][j][k];
char c=low(a[i-2]);
for(int l=0;l<b[j-1].size();l++) if(b[j-1][l]==c) v+=f[i-1][j-1][l];
for(int l=0;l<k;l++) if(b[j][l]==c) v+=f[i-1][j][l];
}
int tot=0;
for(int i=0;i<b[n].size();i++) tot+=f[a.size()][n][i];
if(tot) cout<<a.substr(1)<<" can be formed in "<<tot<<" ways"<<endl;
else cout<<a.substr(1)<<" is not a valid abbreviation"<<endl;
}
return 0;
}
本作品由happyZYM采用知识共享 署名-非商业性使用-相同方式共享 4.0 (CC BY-NC-SA 4.0) 国际许可协议(镜像(简单版)镜像(完整版))进行许可。
转载请注明出处:https://www.cnblogs.com/happyZYM/p/11869575.html (近乎)全文转载而非引用的请在文首添加出处链接。