「一本通 2.3 练习 1」Immediate Decodability 题解

原题来自:ACM Pacific NW Region 1998
Description

给出一些数字串,判断是否有一个数字串是另一个串的前缀。

Input

输入数据为多组数据,每组数据读到 9 时结束。

Output

对于每组数据,如果不存在一个数字串是另一个串的前缀,输出一行 Set t is immediately decodable ,否则输出一行 Set t is not immediately decodable ,其中 t 是这一组数据的组号。

Sample Input :
01
10
0010
0000
9
01
10
010
0000
9
Sample Output :
Set 1 is immediately decodable
Set 2 is not immediately decodable

数字串只包含 0,1,记每个数字串长度为 1 <= l <= 10,则 。每组数据至少有 2 个数字串,至多有 8 个数字串。

字典树的小模板题

类似于 Phone List 例题一,只需要将输入改动再加个结束条件即可

这里把例题一的CODE也放上:

#include <bits/stdc++.h>
#define int long long
using namespace std;

int t,ch[100005][10],bo[100005],tot;
char s[105];
bool insert(char *s) {
	int u=1,len=strlen(s),flag=0;
	for (int i = 0; i < len; i ++) {
		int c = s[i]-'0';
		if (!ch[u][c]) ch[u][c] = ++tot;
		else if (i==len-1) flag = 1;
		u = ch[u][c];
		if (bo[u]) flag=1;
	}
	bo[u] = 1;
	return flag;
}
signed main() {
	cin >> t;
	while (t--) {
		tot = 1;
		int n,ans=0;cin >> n;
		memset(ch,0,sizeof(ch));
		memset(bo,0,sizeof(bo));
		while (n--) {
			cin >> s;
			if (insert(s)) ans = 1;
		}
		if (!ans) cout << "YES\n";
		else cout << "NO\n";
	}
	return 0;
}

本题 CODE :

#include <bits/stdc++.h>
using namespace std;

int t,ch[1000005][5],bo[1000005],tot;
char s[100005];
bool insert(char *s) {
	int u = 1,len = strlen(s),flag = 0;
	for (int i = 0; i < len; i ++) {
		int c = s[i]-'0';
		if (!ch[u][c]) ch[u][c] = ++ tot;
		else if (i == len-1) flag = 1;
		u = ch[u][c];
		if (bo[u]) flag = 1;
	}
	bo[u] = 1;
	return flag;
}
signed main() {
	while (scanf("%s",s) != EOF) {
		memset(ch,0,sizeof(ch));
		memset(bo,0,sizeof(bo));
		t ++;
		tot = 1;
		bool f = 0;
		insert(s);
		// cout << s << endl;
		while(cin >> s && s[0] != '9') {
			// cout << s << endl;
			if (insert(s)) f = 1;
		}
		if (!f) cout << "Set " << t << " is immediately decodable";
		else cout << "Set " << t << " is not immediately decodable";
		puts("");
	}
	return 0;
}

代码解说 :

数据结构

  • Trie树:使用二维数组 ch 实现,ch[u][c] 表示节点 u 的子节点 c 的编号。

  • bo数组:标记节点是否为某个字符串的结尾。

  • 变量

    • t:测试用例编号。

    • tot:动态分配的节点总数,初始根节点为1。

    • ch 和 bo 数组在每次测试前重置,清空Trie。

核心函数 insert

  1. 功能:将字符串插入Trie树,并检查是否存在前缀冲突。

  2. 逻辑

    • 从根节点(u=1)开始遍历字符串。

    • 对每个字符:

      • 若当前字符的子节点不存在,则创建新节点。

      • 若当前字符是最后一个字符且子节点已存在,说明存在更长的字符串(当前字符串是前缀),标记冲突。

      • 若路径中存在已结束的节点(bo[u] 为真),说明当前字符串包含更短的前缀字符串,标记冲突。

    • 最后标记当前字符串的结束节点,返回冲突标志。

主函数逻辑

  1. 循环处理多个测试用例,直到输入结束(EOF)。

  2. 初始化:每个测试用例重置Trie,计数器 t 自增。

  3. 读取字符串

    • 第一个字符串直接插入。

    • 后续字符串通过循环读取,直到遇到以 '9' 开头的字符串结束输入。

  4. 冲突检测:若任何字符串插入时检测到冲突,标记集合为不可解码。

  5. 输出结果:根据冲突标记判断并输出当前集合是否即时可解码。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值