1. 程式人生 > >HDU 1671 (字典樹 || string + vector)

HDU 1671 (字典樹 || string + vector)

目錄

題意:

思路:

1.字典樹

題意:

T個案例,每一個案例給一個n,代表有n個號碼,接著輸入n個號碼。

如果其中有一個號碼是另一個號碼的字首則輸出NO,否則輸出YES。

思路:

1.字典樹

第一反應是字典樹、字首樹嘛……但是之前覺得就很難,不敢寫,然後今天鼓起勇氣研究了一下字典樹,事實上也沒那麼難,重點在於對末尾的判斷,一個是對當前串的判斷,另一個是樹裡的串,所以其實字串的末尾很重要,這邊還是作死用的string,現在想來可能char陣列的'/0'判斷起來還會清晰很多。如果是要統計一個字元出現的次數只要把tail的型別改成int感覺應該也不會很難,但我的話應該會首選map,啊……統計字首的數量也可以用字典樹這麼搞,一會看看有沒有題目。

還有一個問題是記憶體回收的問題,因為這個問題mle了好幾次,也是作死要用new去開空間的關係,如果直接用陣列開好變數空間那麼空間就可以重複使用,也不用去new記憶體了,然後就是遞歸回收的時候要注意。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
using namespace std;

int flag;

struct node
{
	bool tail;
	node* next[10];
	void init()
	{
		tail = false;
		for (int i = 0; i < 10; i++)
			next[i] = NULL;
	}
};

node *newnode()
{
	node *nnode = new node;
	nnode->init();
	return nnode;
}

void insert(node *root,string s)
{
	int len = s.length();
	for (int i = 0; i < len; i++)
	{
		int id = s[i] - '0';
		if (root->next[id] == NULL)
		{
			root->next[id] = newnode();
		}
		else if (root->next[id] != NULL && i == len - 1)//&& 前的可以省略 原因是if語句中的內容與其相反 這裡也要判斷是因為當一個字串的最後一個字元也在樹中存在時,即該字串全部在樹中存在。
		{
			flag = 0;
			return;
		}
		root = root->next[id];
		if (root->tail == true)//即有一個字串到這裡是末尾了 那麼之前那個字串就是本字串的字首。
		{
			flag = 0;
			return;
		}
	}
	root->tail = true;
}

void del(node *p)
{
	if (p == NULL)return;
	for (int i = 0; i < 10; i++)
	{
		if (p->next[i])
		del(p->next[i]);
	}
	delete p;
}

int main()
{
	//ios::sync_with_stdio(false);
	//cin.tie(0);
	int T;
	cin >> T;
	while (T--)
	{
		int n;
		cin >> n;
		string s;
		flag = 1;
		node* root=newnode();
		for (int i = 0; i < n; i++)
		{
			cin >> s;
			if (flag)
			{
				insert(root, s);
			}
		}
		if (flag)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
		del(root);
	}
	system("pause");
	return 0;
}

2.string+vector

當時也是討論區看到的。

vector沒有find可是string有鴨……(其實我也是剛知道= =||| )值的一提的是find函式返回的是找到的位置,如果找不到會返回一個相當於-1的值。

但是……但是……如果兩重迴圈去挨個找當前號碼是不是其他號碼的字首,會超時,很遺憾我再次嘗試這個題目的時候還是會遇到這樣的錯誤,我只能佩服第一個想出這個方法(sort  + v[i].find(v[i-1]))的大佬,我覺得這需要對字典序很敏感才能想到。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <map>
#include <vector>
#include <set>
#include <queue>
using namespace std;

int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	int T;
	cin >> T;
	while (T--)
	{
		int n;
		cin >> n;
		string s;
		vector<string>v;
		for (int i = 0; i < n; i++)
		{
			cin >> s;
			v.push_back(s);
		}
		sort(v.begin(), v.end());
		int flag = 1;		
		for (int i = 0; i < v.size() && flag; i++)
		{
			if (v[i].find(v[i - 1]) != -1)
			{
				flag = 0;
			}
		}
		//for (int i = 0; i < v.size() && flag; i++)//TLE = =|||
		//{
		//	for (int j = 0; j < v.size() && flag; j++)
		//	{
		//		if (i == j)continue;
		//		if (v[j].find(v[i])!=-1)
		//		{
		//			flag = 0;
		//		}
		//	}
		//}
		if (flag)
			cout << "YES" << endl;
		else
			cout << "NO" << endl;
	}
	system("pause");
	return 0;
}