当前位置: 首页 > news >正文

洛谷P12238 [蓝桥杯 2023 国 Java A] 单词分类

[Problem Discription] \color{blue}{\texttt{[Problem Discription]}} [Problem Discription]

在这里插入图片描述
Copy from luogu.

[Analysis] \color{blue}{\texttt{[Analysis]}} [Analysis]

既然都是字符串前缀的问题了,那当然首先就应该想到 Trie \text{Trie} Trie 树。

我们可以发现这么一个性质,如果选从根到 Trie \text{Trie} Trie 树上某一点形成给定字符串作为前缀,那么子树内所有的字符串都会被归为这个类,子树外的其它字符串都不会被归为这个类。

于是可以想到在 Trie \text{Trie} Trie 上进行 dp \text{dp} dp。用 f u , k f_{u,k} fu,k 表示把子树 u u u 内的字符串分为 k k k 类的方案数。

根据上面的性质,其实这个 dp \text{dp} dp 等价于从 u u u 及其子树中选出 k k k 个点的方案数,因而转移方程显然。

但是需要注意的是,如果选择了 u u u 这个点,那么 u u u 的子树的点都不可以被选取,不然就会有些字符串被分入两个组中。当然,如果 k = 1 k=1 k=1,那么选择 u u u 也是可能的合法的选择。

另外,因为每个字符串都要被分入其中一个组,因此 k k k 不能小于等于 0 0 0

考虑清楚边界情况就可以开始写代码了。

另外,由于每个节点最多也就 3 3 3 个子树,因此没必要写得那么复杂,枚举每棵子树内选取多少个点就可以了。

时间复杂度最多 O ( N K × max ⁡ { ∣ s ∣ } ) O(NK \times \max \{ |s| \}) O(NK×max{s})。其中 max ⁡ { ∣ s ∣ } \max \{ |s| \} max{s} 表示字符串长度的最大值。

Code \color{blue}{\text{Code}} Code

const int mod=1e9+7;
const int N=210,M=110,L=2010;int id(char ch){switch (ch){case 'l': return 0;case 'q': return 1;case 'b': return 2;default: return -1;}
}struct Trie_Tree{int ch[L][3],ndcnt,cnt[L],child[L];bool flag[L];void init(){memset(ch,-1,sizeof(ch));memset(cnt,0,sizeof(cnt));memset(flag,false,sizeof(flag)); memset(child,0,sizeof(child));ndcnt=0;}void insert(string s){int l=s.length(),u=0;for(int i=0;i<l;i++){int c=id(s[i]);if (ch[u][c]==-1){ch[u][c]=++ndcnt;++child[u]; }++cnt[u];//统计字符串的数量 u=ch[u][c];}++cnt[u];flag[u]=true;}
}trie;int f[L][M],n,m;int dp(int u,int k){ if (trie.cnt[u]<k) return 0;if (~f[u][k]) return f[u][k];if (k<=0) return 0; if (trie.flag[u]) return k==1;int res=((k==1)?1:0);if (trie.child[u]==1){int c;if (~trie.ch[u][0]) c=trie.ch[u][0];else if (~trie.ch[u][1]) c=trie.ch[u][1];else c=trie.ch[u][2];res=(res+dp(c,k))%mod;}else if (trie.child[u]==2){int c1,c2;if (~trie.ch[u][0]){c1=trie.ch[u][0];if (~trie.ch[u][1]) c2=trie.ch[u][1];else c2=trie.ch[u][2];}else c1=trie.ch[u][1],c2=trie.ch[u][2];for(int i=1;i<k;i++)res=(res+1ll*dp(c1,i)*dp(c2,k-i)%mod)%mod;}else{for(int i=1;i<k;i++)for(int j=1;j<k-i;j++)res=(res+1ll*dp(trie.ch[u][0],i)*dp(trie.ch[u][1],j)%mod*dp(trie.ch[u][2],k-i-j)%mod)%mod;}return f[u][k]=res;
}int main(){cin>>n>>m;trie.init();for(int i=1;i<=n;i++){string s;cin>>s;trie.insert(s);}memset(f,-1,sizeof(f));printf("%d",dp(0,m));return 0;
}

相关文章:

  • 基于LVS+Keepalived+NFS的高可用负载均衡集群部署
  • 基于大模型的大肠息肉全程管理研究报告
  • 破茧成蝶:一家传统制造企业的年轻化转型之路
  • 总结小程序的坑
  • ​钓鱼网页散播银狐木马,远控后门威胁终端安全
  • 数字中国浪潮下:Coremail AI赋能邮件办公,筑牢安全防线引领转型
  • VSCode突然连接不上服务器(已解决)
  • “情况说明“以后,Unity XR 开发者如何选择?
  • JavaWeb:后端web基础(TomcatServletHTTP)
  • Linux《进程概念(中)》
  • SSM书籍管理(业务编写)
  • c#WebsocketSever
  • 【3D基础】顶点法线与平面法线在光照与PBR中的区别与影响
  • 第13讲:图形尺寸与分辨率设置——适配论文版面,打造专业图稿!
  • upload-labs PASS 1-5通关
  • 【无报错,亲测有效】如何在Windows和Linux系统中查看MySQL版本
  • 第一章 应急响应- Linux入侵排查
  • PyTorch 深度学习实战(23):多任务强化学习(Multi-Task RL)之扩展
  • C++23中的std::forward_like:完美转发的增强
  • Qt入门——什么是Qt?
  • 美国参议院投票通过戴维·珀杜出任美国驻华大使
  • 新华社评论员:汇聚起工人阶级和广大劳动群众的磅礴力量
  • 十四届全国人大常委会举行第四十三次委员长会议 ,听取有关草案和议案审议情况汇报
  • 苏州一季度GDP为6095.68亿元,同比增长6%
  • 中消协发布“五一”消费提示:践行“光盘行动”,抵制餐饮浪费
  • 人民日报:应对外贸行业风险挑战,稳企业就是稳就业