在字典中搜索具有给定前缀和后缀的字符串以进行 Q 查询
给定一个由N个字符串和Q个查询组成的数组arr[] ,形式为两个字符串prefix和suffix ,每个查询的任务是在给定数组中找到具有给定prefix和suffix的任何一个字符串。如果不存在这样的字符串,则打印“-1” 。
例子:
Input: arr[] = {“apple”, “app”, “biscuit”, “mouse”, “orange”, “bat”, “microphone”, “mine”}, Queries[] = {{a, e}, {a, p}}
Output:
apple
app
Explanation:
Query 1: String “apple” is the only word in the given dictionary with the given prefix “a” and suffix “e”.
Query 2: String “app” is the only word in the given dictionary with the given prefix “a” and suffix “p”.
Input: arr[] = {“apple”, “app”, “biscuit”, “mouse”, “orange”, “bat”, “microphone”, “mine”}, Queries[] = {{mi, ne}}
Output: mine
朴素方法:解决给定问题的最简单方法是遍历每个查询的给定字符串数组arr[] ,如果存在具有给定前缀和后缀的任何此类字符串,则打印该字符串。否则,打印“-1” 。
时间复杂度: O(Q*N*M),其中 M 是字符串的最大长度。
辅助空间: O(1)
高效方法:上述方法也可以通过使用 Trie 数据结构来解决问题进行优化。可以通过以下方式修改 trie 的实现以支持前缀和后缀搜索:
- 假设字典中的给定单词是apple 。在这种情况下,单词apple被插入到 Trie 中。但要支持前缀和后缀同时搜索的话: e{apple, le{apple, ple{apple, pple{apple, apple{apple可以插入到Trie中。
- 请注意,这些单词的形式为suffix{word ,其中suffix是给定单词的所有可能的后缀。
- 特殊字符{插入在后缀和单词之间以分隔它们。可以使用除字母表之外的任何特殊字符来代替{ ,但首选{ ,因为它的 ASCII 值是 123,比z的 ASCII 值大一。
请按照以下步骤解决问题:
- 使用变量i遍历数组arr[]中的所有字符串,并执行以下步骤:
- 初始化一个字符串 , temp为'{' + arr[i] 。
- 遍历字符串中的所有字符,从末尾arr[i]开始,将每个字符附加到字符串temp的前面,然后将此字符串插入到 trie 中。
- 创建 trie 后,遍历所有查询并执行以下步骤:
- 存储当前查询的前缀和后缀字符串。
- 初始化一个字符串, t为后缀+'{'+前缀,在trie中搜索。
- 如果找不到,则打印“-1” 。否则,打印匹配的字符串。
下面是上述方法的实现:
C++
// C++ program for the above approach
#include
using namespace std;
// Trie Node
struct Trie {
Trie* arr[27] = { NULL };
// Stores the index of the word
// in the dictionary
int idx;
};
// Root node of the Trie
Trie* root = new Trie();
// Function to insert the words in
// the Trie
void insert(string word, int i)
{
// Temporary pointer to the root
// node of the Trie
Trie* temp = root;
// Traverse through all the
// characters of current word
for (char ch : word) {
// Make a Trie Node, if not
// already present
if (temp->arr[ch - 'a'] == NULL) {
Trie* t = new Trie();
temp->arr[ch - 'a'] = t;
}
temp = temp->arr[ch - 'a'];
temp->idx = i;
}
}
// Function to search the words in Trie
int search(string word)
{
Trie* temp = root;
// Traverse through all the
// characters of current word
for (char ch : word) {
// If no valid Trie Node exists
// for the current character
// then there is no match
if (temp->arr[ch - 'a'] == NULL)
return -1;
temp = temp->arr[ch - 'a'];
}
// Return the resultant index
return temp->idx;
}
// Function to search for a word in
// the dictionary with the given
// prefix and suffix for each query
void findMatchingString(
string words[], int n,
vector > Q)
{
string temp, t;
// Insertion in the Trie
for (int i = 0; i < n; i++) {
// Form all the words of the
// form suffix{word and insert
// them in the trie
temp = "{" + words[i];
for (int j = words[i].size() - 1;
j >= 0; j--) {
t = words[i][j] + temp;
temp = t;
// Insert into Trie
insert(t, i);
}
}
// Traverse all the queries
for (int i = 0; i < Q.size(); i++) {
string prefix = Q[i][0];
string suffix = Q[i][1];
string temp = suffix + "{" + prefix;
// Stores the index of
// the required word
int res;
// Store the index of the
// word in the dictionary
res = search(temp);
// In case of match, print
// the corresponding string
if (res != -1) {
cout << words[res] << '\n';
}
// Otherwise, No match found
else
cout << "-1\n";
}
}
// Driver Code
int main()
{
string arr[]
= { "apple", "app", "biscuit",
"mouse", "orange", "bat",
"microphone", "mine" };
int N = 8;
vector > Q = { { "a", "e" }, { "mi", "ne" } };
findMatchingString(arr, N, Q);
return 0;
}
apple
mine
时间复杂度: O(N*M 2 + Q*M),其中M是所有字符串中的最大长度
辅助空间: O(N*M 2 )