给定一组个字符串,为每个字符串找出能够唯一识别该字符串的最小前缀。
给定一组个字符串,为每个字符串找出能够唯一识别该字符串的最小前缀。
第一行输入一个整数 n 表示字符串个数后面n行,每行一个字符串,一共n串互不相同的字符串。(2 <= n <= 100,字符串长度不超过100)
输出n行,每行一个字符串,依次是每个字符串的最小可唯一识别前缀
5 meituanapp meituanwaimai dianpingliren dianpingjiehun mt
meituana meituanw dianpingl dianpingj mt
如果一个字符串S是另一个字符串T的前缀,则S的最小可识别前缀为S;
#include<iostream>
(720)#include<vector>
#include<string>
using namespace std;
class trie_node{
public:
int cnt;
trie_node* next[26];
trie_node(){
cnt=1;
for(int i=0;i<26;i++){
next[i]=nullptr;
}
}
};
int main(){
trie_node* root=new trie_node();
int n=0;
cin>>n;
vector<string> strs(n);
for(int i=0;i<n;i++){
string tmp;
cin>>tmp;
strs[i]=tmp;
trie_node* p=root;
for(int j=0;j<tmp.length();j++){
if(p->next[tmp[j]-'a']!=nullptr){
p->next[tmp[j]-'a']->cnt++;
}
else{
p->next[tmp[j]-'a']=new trie_node();
}
p=p->next[tmp[j]-'a'];
}
}
for(int i=0;i<n;i++){
trie_node* p=root;
int j=0;
for(;j<strs[i].length();j++){
if(p->next[strs[i][j]-'a']->cnt == 1){
cout<<strs[i].substr(0,j+1)<<endl;
break;
}
p=p->next[strs[i][j]-'a'];
}
if(j==strs[i].length()){
cout<<strs[i]<<endl;
}
}
return 0;
} #include<bits/stdc++.h>
using namespace std;
int n;
int mod=1e9+7;
vector<string> v,v2;
bool vis[200];
int h[200];
int main(){
ios::sync_with_stdio(0);
cin>>n;
v=vector<string>(n);
v2=vector<string>(n);
for (int i=0;i<n;i++){
cin>>v[i];
}
memset(vis,0,sizeof(vis));
memset(h,0,sizeof(h));
int w=1;
for (int i=0;i<100;i++){
for (int j=0;j<n;j++){
if(vis[j] || i>=v[j].size()){
continue;
}
h[j]=(h[j]+w*(v[j][i]))%mod;
}
for (int j=0;j<n;j++){
if(vis[j]) continue;
bool f=true;
for (int k=0;k<n;k++){
if(j==k || vis[k] ){
continue;
}
if(h[j]==h[k]){
f=false;
break;
}
}
if(f){
vis[j]=true;
v2[j]=v[j].substr(0,i+1);
}
}
w=(w*137)%mod;
}
for (auto s:v2){
cout<<s<<endl;
}
}
trie树
#include <bits/stdc++.h>
using namespace std;
const int N = 10010;
int son[N][26], cnt[N], idx;
int n;
void insert(string &str){
int p = 0;
for (int i = 0; str[i]; i++){
int u = str[i] - 'a';
if (!son[p][u]) son[p][u] = ++idx;
// 计算每个字符出现的次数
cnt[son[p][u]]++;
p = son[p][u];
}
}
string query(string &str){
int p = 0;
for (int i = 0; str[i]; i++){
int u = str[i] - 'a';
// 出现次数为1的字符为终点的字符串为最小前缀
if (cnt[son[p][u]] == 1) return str.substr(0, i + 1);
p = son[p][u];
}
return str;
}
int main(){
cin >> n;
vector strs;
while (n--) {
string str;
cin >> str;
insert(str);
strs.push_back(str);
}
for (auto && x : strs){
cout << query(x) << endl;
}
return 0;
}
class solution:
def __init__(self):
self.pretree={}
def inset(self,a):
temp=self.pretree
for x in a:
if x not in temp:
temp[x]={}
temp=temp[x]
def core(self,a):
temp=self.pretree
res=''
for x in a:
if x in temp:
res+=x
temp=temp[x]
else:
res+=x
return res
return res
n=int(input())
strings=[]
res=[]
for i in range(n):
strings.append(input())
for string in strings:
a=solution()
for string_else in strings:
if string==string_else:
continue
a.inset(string_else)
res.append(a.core(string))
for x in res:
print(x) #include <iostream>
#include <set>
#include <map>
#include <vector>
#include <string>
#include <string.h>
#include <memory>
using namespace std;
class Trie
{
public:
struct Node
{
map<char, shared_ptr<Node>> subs;
int cnt;
Node()
{
cnt = 1;
}
};
typedef map<char, shared_ptr<Node>>::iterator SubsIter;
Trie()
{
root = make_shared<Node>();
}
void build(const string &str)
{
shared_ptr<Node> tmp = root;
int len = str.length();
SubsIter iter;
for (int idx = 0; idx < len; ++idx)
{
iter = tmp->subs.find(str[idx]);
if (iter == tmp->subs.end())
{
shared_ptr<Node> new_node = make_shared<Node>();
tmp->subs.insert(make_pair(str[idx], new_node));
}else{
++iter->second->cnt;
}
tmp = tmp->subs[str[idx]];
}
}
string min_pre(const string &str)
{
shared_ptr<Node> tmp = root;
int len = str.length();
SubsIter iter;
for (int idx = 0; idx < len; ++idx)
{
iter = tmp->subs.find(str[idx]);
if (iter == tmp->subs.end())
{
return "";
}
if (iter->second->cnt == 1)
{
return str.substr(0, idx + 1);
}
tmp = iter->second;
}
return str;
}
private:
shared_ptr<Node> root;
};
int main()
{
int n;
cin >> n;
vector<string> cell(n);
Trie tree;
for (int idx = 0; idx < n; ++idx)
{
cin >> cell[idx];
tree.build(cell[idx]);
}
for(int idx = 0; idx < n; ++ idx)
{
cout<<tree.min_pre(cell[idx])<<endl;
}
return 0;
}
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = sc.nextInt();
String[] ss = new String[n];
String[] res = new String[n];
for (int i = 0; i < n; i++) {
ss[i] = sc.next();
res[i] = ss[i];
}
//从第一个字符串开始寻找
for (int j = 0; j < n; j++) {
//从第一个字符开始寻找最短前缀
for (int i = 0; i <= ss[j].length(); i++) {
boolean *** = true;
//每个字符串寻找一次
for (String cur : ss) {
//TODO 排除当前
if (!ss[j].equals(cur) && cur.length() >= i && ss[j].substring(0, i).equals(cur.substring(0, i))) {
//匹配上了说明当前长度不够
*** = false;
break;
}
}
if (***) {
res[j] = ss[j].substring(0, i);
break;
}
}
}
for (int i = 0; i < n; i++) {
System.out.println(res[i]);
}
}
}
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int n = Integer.parseInt(scanner.nextLine());
List<String> list = new ArrayList<>();
for (int i = 0; i < n ; i++) {
list.add(scanner.nextLine());
}
List<String> match = match(list);
for (String element : match){
System.out.println(element);
}
}
/**
* 思路: 使用暴力破解法
* (1)、 匹配第一个字符观察其他字符是否也出现此字符,出现则继续匹配往下匹配,直至其他字符串在此索引下无相同的字符,或者该字符串匹配到最后一个
* (2)、该字符穿即时最小可识别前缀
*/
private static List<String> match(List<String> list) {
List<String> returnList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
String matchString = list.get(i);
int beMaxLength = Integer.MIN_VALUE;
for (int j = 0; j < list.size(); j++) {
int index = 0;
if(j == i){
continue;
}
String beMatchString = list.get(j);
while (index < matchString.length() && index < beMatchString.length()
&& matchString.charAt(index) == beMatchString.charAt(index)) {
index++;
}
beMaxLength = Math.max(index, beMaxLength);
}
if(beMaxLength == matchString.length()){
returnList.add(matchString.substring(0,beMaxLength));
}else{
returnList.add(matchString.substring(0,beMaxLength + 1));
}
}
return returnList;
}
} #include <iostream>
#include <unordered_map>
#include <vector>
using namespace std;
class Node {
public:
int count = 1;
unordered_map<char, Node*> child;
};
int main()
{
int n;
cin >> n;
vector<string> strs(n);
auto root = new Node();
for (int i = 0; i < n; i++)
{
string input;
cin >> input;
strs[i] = input;
auto ptr = root;
for (int j = 0; j < input.size(); j++) {
if (ptr->child.find(input[j]) == ptr->child.end()) {
ptr->child.insert({ input[j],new Node() });
}
else
ptr->child[input[j]]->count++;
ptr = ptr->child[input[j]];
}
}
for (int i = 0; i < n; i++) {
auto ptr = root;
int j = 0;
while (j < strs[i].size() && ptr->child[strs[i][j]]->count != 1)
{
ptr = ptr->child[strs[i][j++]];
}
cout << strs[i].substr(0, j + 1) << endl;
}
}
def commonSubingString(s, t): if s == t: return 0 n = 0 for ss, tt in zip(s, t): if ss == tt: n += 1 else: break return n if __name__ == '__main__': n = int(input()) data = [] for i in range(n): data.append(input()) for d in data: r = max([commonSubingString(d, t) for t in data]) print(d[:min(r + 1, len(d))])python 暴力解法,直接搜索目标字符串和其他字符串最长前缀,然后在此基础上+1。
import java.util.*;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int n = Integer.valueOf(sc.nextLine());
List<MyC> strs = new ArrayList<>();
String[] ans = new String[n];
for (int i = 0; i < n; i++) {
strs.add(new MyC(sc.nextLine(), i));
if(strs.get(i).s.length() == 0) {
ans[i] = "";
}
}
if (n == 1) {
System.out.println(strs.get(0).s.substring(0, 1));
} else {
dfs(strs, 0, ans);
for (String w : ans) {
System.out.println(w);
}
}
}
private static void dfs(List<MyC> list, int cur_idx, String[] ans) {
if (list == null || list.size() == 0) {
return ;
}
if (list.size() == 1) {
MyC w = list.get(0);
ans[w.idx] = w.s.substring(0, cur_idx);
return;
}
List<MyC>[] rec = new ArrayList[128];
for (int i = 0; i < 128; i++) {
rec[i] = new ArrayList<>();
}
for (MyC myC : list) {
if (myC.s.length() == cur_idx) {
ans[myC.idx] = myC.s;
} else {
rec[myC.s.charAt(cur_idx)].add(myC);
}
}
for (List<MyC> myCS : rec) {
dfs(myCS, cur_idx + 1, ans);
}
}
}
class MyC {
String s;
int idx;
MyC (String s, int idx) {
this.s = s;
this.idx = idx;
}
} import java.util.*;
public class Main{
static Map<String, String> map = new HashMap<>();
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
int n = scan.nextInt();
scan.nextLine();
String[] s = new String[n];
List<String> list = new ArrayList<>();
for(int i= 0; i<n; i++){
s[i] = scan.nextLine();
list.add(s[i]);
}
helper(list, 0);
for(int i= 0; i<n; i++){
System.out.println(map.get(s[i]));
}
}
public static void helper(List<String> list, int level){
if(list.size()==1){
map.put(list.get(0), list.get(0).substring(0, level));
return;
}
for(int i = 0; i<list.size(); i++){
if(level == list.get(i).length()){
map.put(list.get(i), list.get(i));
list.remove(i);
i--;
}
}
int[] visited = new int[list.size()];
for(int i = 0; i<list.size(); i++){
if(visited[i] == 0){
List<String> temp = new ArrayList<>();
int t = list.get(i).charAt(level);
for(int j = i; j<list.size(); j++){
if(list.get(j).charAt(level)==t){
temp.add(list.get(j));
visited[j]=1;
}
}
if(list.size()>0)
helper(temp, level+1);
}
}
}
}
// 题目:https://www.nowcoder.com/test/question/done?tid=33823885&qid=894534#summary
#include <iostream>
#include <string>
#include <vector>
#include <array>
class Trie {
public:
Trie() { root_ = new TreeNode; }
~Trie() {__destroy(root_); }
void insert(std::vector<std::string>&& words) {
for(const auto& word : words) {
TreeNode* curr = root_;
for(const auto& ch : word) {
int idx = ch-'a';
if(curr->nexts[idx] ==nullptr)
{
curr->nexts[idx] = new TreeNode;
}
else
{
++curr->nexts[idx]->path;
}
curr = curr->nexts[idx];
}
}
words_.swap(words);
}
// 那些公共前缀的 path 值肯定大于1
// 主要找到大于1的path,就是该分支单词最短可识别前缀
void solve() {
for(const auto& word : words_) {
TreeNode* curr = root_;
int idx=0;
for(; idx < word.size(); ++idx) {
int index = word[idx]-'a';
if(curr->nexts[index]->path ==1)
{
std::cout<<word.substr(0, idx+1)<<std::endl;
break;
}
curr = curr->nexts[index];
}
if(idx == word.size()) {
std::cout<<word<<std::endl;
}
}
}
private:
struct TreeNode {
uint64_t path; // 经过某个单词的次数
std::array<TreeNode*, 26> nexts;
TreeNode() : path(1)
{
nexts.fill(nullptr);
}
};
// 析构创建的节点
void __destroy(TreeNode* root) {
if(root ==nullptr)
return;
for(const auto& node : root->nexts) {
__destroy(node);
}
delete root;
root =nullptr;
}
TreeNode* root_;
std::vector<std::string> words_;
};
int main(int argc, char const *argv[]) {
int N=0;
std::cin>>N;
std::vector<std::string> words;
words.reserve(N);
std::string word;
while(N--) {
std::cin>>word;
words.emplace_back(std::move(word));
}
Trie* trie = new Trie;
trie->insert(std::move(words));
trie->solve();
delete trie;
trie =nullptr;
return 0;
}
#include<iostream>
(720)#include<vector>
#include<unordered_map>
using namespace std;
struct Node {
string data = "";
int cnt = 0;
unordered_map<char, Node*> nexts;
};
void getRes(Node* node, unordered_map<string, string>&res,string& tmp) {
if (node == NULL) return;
if (node->data != "")
res[node->data] = tmp;
if (node->cnt == 1) {
string str(tmp);
while (node->nexts.size() > 0) {
str += node->nexts.begin()->first;
node = node->nexts.begin()->second;
}
res[node->data] = tmp;
}
else {
for (auto it = node->nexts.begin(); it != node->nexts.end(); ++it) {
tmp += it->first;
getRes(it->second, res, tmp);
tmp.pop_back();
}
}
}
void minPrefix(vector<string>& strs) {
Node* head = new Node();
for (auto& str : strs) {
Node* node = head;
for (int i = 0; i < str.size(); ++i) {
if (node->nexts.find(str[i]) == node->nexts.end())
node->nexts[str[i]] = new Node();
node = node->nexts[str[i]];
node->cnt++;
}
node->data = str;
}
unordered_map<string, string>res;
string tmp = "";
getRes(head, res, tmp);
for (int i = 0; i < strs.size(); ++i) {
strs[i] = res[strs[i]];
}
}
int main() {
int n;
cin >> n;
vector<string>strs(n);
for (int i = 0; i < n; ++i)
cin >> strs[i];
minPrefix(strs);
for (int i = 0; i < n; ++i)
cout << strs[i] << endl;
} import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scan=new Scanner(System.in);
int n=Integer.valueOf(scan.nextLine());
String ss[]=new String[n];
for(int i=0;i<n;i++){
ss[i]=scan.nextLine();
}
String s1[]=new String[n];
for(int i=0;i<n;i++){
int t=0;
boolean flage=true;
while(flage==true){
flage=false;
for(int j=0;j<i;j++){
if(ss[j].length()>t)
if(ss[j].charAt(t)==ss[i].charAt(t))
flage=true;
}
for(int j=i+1;j<n;j++){
if(ss[j].length()>t)
if(ss[j].charAt(t)==ss[i].charAt(t))
flage=true;
}
t++;
if(t>=ss[i].length())
flage=false;
}
s1[i]=ss[i].substring(0,t);
}
for(int i=0;i<n;i++){
System.out.println(s1[i]);
}
}
} import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
minPrefix();
}
private static void minPrefix() {
Scanner scanner = new Scanner(System.in);
int n = scanner.nextInt();
String[] strs = new String[n];
int maxLen = 0;
for (int i = 0; i < n; i++) {
strs[i] = scanner.next();
maxLen = Math.max(maxLen, strs[i].length());
}
int[] minLen = new int[n]; // minLen[i]: strs[i]的最小前缀长度
for (int i = 1; i <= maxLen; i++) {
Map<String, Integer> map = new HashMap<>();
for (int j = 0; j < n; j++) {
if(minLen[j] != 0)
continue;
if(i == strs[j].length()) {
minLen[j] = i;
}
String str = strs[j].substring(0, i);
map.put(str, map.getOrDefault(str, 0) + 1);
}
for(int j = 0; j < n; j++){
if(minLen[j] != 0)
continue;
String str = strs[j].substring(0, i);
if(map.get(str) == 1)
minLen[j] = i;
}
}
for(int i = 0; i < n; i++){
System.out.println(strs[i].substring(0, minLen[i]));
}
}
} #include<iostream>
(720)#include<string>
#include<vector>
(721)#include<algorithm>
#include<unordered_map>
using namespace std;
int main(){
int N;
cin>>N;
vector<string> vec;
string temp;
size_t max_len=0; // 所有字符串最大长度
for(int i=0;i<N;i++){
cin>>temp;
max_len=max(max_len, temp.size());
vec.push_back(temp);
}
vector<int> pre_len(vec.size(),0); // 所有字符串前缀长度,初始为0
// 遍历前缀长度
for(int i=1;i<=max_len;i++){
// 若前缀长度为i,将所有字符串的前缀统计个数
unordered_map<string, int> map;
for(int j=0;j<vec.size();j++){
if(pre_len[j]>0) continue;
string pre=vec[j].substr(0,i);
if(map.find(pre)==map.end()){
map[pre]=1;
}else{
map[pre]++;
}
}
// 前缀个数为1的,可以作为其最终的前缀结果
for(int j=0;j<vec.size();j++){
if(pre_len[j]>0) continue;
string pre=vec[j].substr(0,i);
if(map[pre]==1) pre_len[j]=i;
}
}
for(int i=0;i<pre_len.size();i++){
cout<<vec[i].substr(0,pre_len[i])<<endl;
}
return 0;
} //前缀树
import java.util.*;
public class Main{
public static void main(String[]args){
Scanner sc=new Scanner(System.in);
int n=sc.nextInt();
sc.nextLine();
String[] strArr=new String[n];
PrefixTree tree=new PrefixTree();
for(int i=0;i<n;i++){
strArr[i]=sc.nextLine();
tree.insert(strArr[i]);
}
for(String s:strArr)
System.out.println(tree.findMaxPrefix(s));
}
public static class TreeNode{
public int path;
public int end;
public HashMap<Character,TreeNode> map;
public TreeNode(){
path=0;
end=0;
map=new HashMap<Character,TreeNode>();
}
}
public static class PrefixTree{
private TreeNode root;
public PrefixTree(){
root=new TreeNode();
}
public void insert(String word){
if(word==null)
return;
char[]chs=word.toCharArray();
TreeNode node=root;
for(int i=0;i<chs.length;i++){
if(!node.map.containsKey(chs[i]))
node.map.put(chs[i],new TreeNode());
node=node.map.get(chs[i]);
node.path++;
}
node.end++;
}
public String findMaxPrefix(String word){
if(word.isEmpty())
return "";
TreeNode node=root;
String res="";
char[]chs=word.toCharArray();
for(int i=0;i<chs.length;i++){
if(node.map.containsKey(chs[i])){
node=node.map.get(chs[i]);
res+=chs[i];
if(node.path==1)
return res;
}else
return "";
}
return res;
}
}
} import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner scanner = new Scanner(System.in);
int num = scanner.nextInt();
scanner.nextLine();
String[] strings = new String[num];
for(int i=0; i<num; ++i){
strings[i] = scanner.nextLine();
}
scanner.close();
TreeNode treeNode = new TreeNode();
for(int i=0; i<num; ++i){
treeNode.insert(strings[i]);
}
for(int i=0; i<num; ++i){
treeNode.prefix(strings[i]);
}
}
static class TreeNode{
private int path;
private boolean isWord;
private Map<Character, TreeNode> next;
public TreeNode(){
path = 0;
next = new HashMap<Character, TreeNode>();
isWord = false;
}
public void insert(String s){
TreeNode curr = this;
for(int i=0; i<s.length(); ++i){
char c = s.charAt(i);
++curr.path;
if(curr.next.containsKey(c)){
curr = curr.next.get(c);
}else {
curr.next.put(c, new TreeNode());
curr = curr.next.get(c);
}
}
curr.isWord = true;
}
public void prefix(String s){
TreeNode curr = this;
for(int i=0; i<s.length(); ++i){
if(curr.next.get(s.charAt(i)).isWord){
if(i==(s.length()-1)){
System.out.println(s.substring(0,i+1));
break;
}else {
curr = curr.next.get(s.charAt(i));
}
}else{
if(curr.next.get(s.charAt(i)).path==1){
System.out.println(s.substring(0,i+1));
break;
}
curr = curr.next.get(s.charAt(i));
}
}
}
}
}
import java.util.*;
public class Main{
public static String iskmp(String a,String b){
int n = (a.length()>=b.length())? b.length() : a.length();
for(int i=0;i<n;i++){
if(a.charAt(i)!=b.charAt(i)){
return a.substring(0,i);
}
}
return (a.length()>=b.length())? b : a;
}
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int n = in.nextInt();
List<String> strs = new ArrayList<>();
for(int i=0;i<n;i++){
String ne = in.next();
strs.add(ne);
}
String[] result = new String[n];
for(int i=0;i<strs.size();i++){
int max=0;
for(int j=0;j<strs.size();j++){
if(i==j){
continue;
}
int now = iskmp(strs.get(i),strs.get(j)).length();
if(now>max){
max = now;
}
}
if(strs.get(i).length()==max){
result[i]=strs.get(i);
}
else {
result[i] = strs.get(i).substring(0, max + 1);
}
}
for(int i=0;i<n;i++){
System.out.println(result[i]);
}
}
}