Este artigo descreve o algoritmo de segmentação de palavras correspondente bidirecional implementado pelo Java. Compartilhe -o para sua referência, como segue:
Vários algoritmos populares de segmentação de palavras são: método de segmentação de palavras com base na correspondência de strings, método de segmentação de palavras com base na compreensão e no método de segmentação de palavras com base em estatísticas. Este artigo usa o método de correspondência de string.
Particípio máximo de correspondência máxima:
Esse algoritmo é implementado com base no dicionário de particípio do Word, que executa a correspondência de segmentação do lado esquerdo da string. Se o dicionário existir, retorna a palavra dividida e corta a palavra da sequência anterior e loops para cortar até que o tamanho da corda seja 0.
Por exemplo: STR = "Somos todos estudantes da Escola de Engenharia de Informações da Universidade Noroeste A&F". (Suponha que definamos o comprimento máximo de corte máx.
1. Defina a palavra Comprimento do particípio Len = Max, retire os caracteres len da palavra esquerda = "Somos todos na agricultura e silvicultura do noroeste" e combinam com a palavra no dicionário;
2. Se não houver essa palavra no dicionário, remova o último caractere e atribua -o ao Word, e o valor len é reduzido em 1;
3. Repita a etapa 2 até que a palavra seja encontrada no dicionário ou len = 1, saia do loop;
4. Corte as palavras divididas de STR e repita as etapas 1, 2 e 3 até que o STR seja decomposto.
Particípio máximo de correspondência máxima reversa:
Como o algoritmo de segmentação de palavras para a frente, ele simplesmente começa do lado direito da corda até que o comprimento da string seja 0. Não vou entrar em detalhes aqui.
Particípio combinando de duas vias:
Esse método é tornar o particípio de ambiguidade para segmentar a ambiguidade com base no particípio avançado e no particípio reverso. Propor a implementação do "algoritmo de comer cobra". A string para executar a segmentação de palavras é alimento. Existem 2 cobras gulosas, uma come da esquerda para a direita; O outro come da direita para a esquerda. Enquanto os resultados do particípio esquerdo e direito forem ambíguos, as duas cobras mordem. A corda que a cobra come se torna particípio. Se sempre houver ambiguidade entre os particípios esquerdo e direito, as duas cobras continuarão comendo. Quando duas cobras comem o cruzamento entre as cordas, definitivamente não haverá ambiguidade. Nesse momento, o particípio na barriga de cobra gananciosa à esquerda, não há ambiguidade no meio, e o particípio na barriga de cobra gananciosa à direita, três dos quais são o particípio final.
Este artigo é dividir todo o parágrafo em palavras. Primeiro, o parágrafo é dividido em frases com base em marcas de pontuação e, em seguida, cada frase é emitida para dividir a palavra.
pacote cn.nwsuaf.spilt; importar java.io.bufferedreader; importar java.io.fileReader; importar java.io.ioException; importar java.util.arrayList; importação java.util.hashmap; import java.util.list; importSba.util.Map.Minern. O algoritmo de segmentação de palavras máximas de correspondência bidirecional para a frente e reversa* @Author Liu Yonglang**/public class Wordspilt {/*** Dicionário de segmentação de palavras de armazenamento*/mapa privado <string, número inteiro> map = new Hashmap <string, integger> (); / *** O comprimento máximo de corte de palavras é cinco caracteres chineses*/ privado int max_length = 5; /** * Leia a palavra Dicionário de Particípios no método de construção e armazene -o no mapa * * @throws ioexception */public wordspilt () lança ioexception {buffarredreader br = new buffarredreader (novo fileReader ("src/dict.txt")); Linha de string = null; while ((line = Br.readline ())! = null) {line = line.trim (); map.put (linha, 0); } Br.Close (); } / *** Defina o comprimento máximo de corte da palavra** @param max* Comprimento máximo de corte de palavras* / public void setMaxLength (int max) {this.max_length = max; } / ** * Obtenha o comprimento máximo de corte da palavra atual, o padrão é 5 (5 caracteres chineses) * * @return Comprimento máximo atual da palavra * / public int getMaxLength () {return this.max_length; } / ** * Algoritmo de corte de palavras máximo correspondente * * @param slingttr * string a ser dividido * @param lefttoright * A direção do fatiamento, true é da esquerda para a direita, False é a string dividida da direita para a esquerda * @return * / list public <string> Slitild (string spiltStr, boolean esquerdtoright) {/ nulo; // Armazene a lista de strings split de correspondência positiva <String> palavras de esquerda = new ArrayList <String> (); // Armazene a lista de strings split de correspondência negativa <String> stronTords = new ArrayList <String> (); // string para cortar string word = null; // Tome o comprimento da palavra, inicialize com o valor máximo int wordLength = max_length; // está na posição atual da string int position = 0; // O comprimento da string foi processado int comprimento = 0; // Remova os espaços extras na string spiltstr = spiltstr.Trim (). Replaceall ("// s+", ""); // Quando a string a ser cortada não é fatiada, a segmentação do loop enquanto (comprimento <spiltstr.length ()) {// se o comprimento da sequência que não foi cortado for menor que o valor máximo, deixe o comprimento da palavra igual ao comprimento da palavra; // Caso contrário, pegue o valor padrão else wordLength = max_length; // Se for uma correspondência máxima para a frente, comece a cortar a partir da posição do spiltstr if (lefttoright) {position = length; word = spiltstr.substring (posição, posição + wordLength); } // Se for uma correspondência máxima inversa, comece a cortar a partir do final do SpiltStr else {POSITION = SPILTSTR.Length () - comprimento; word = spiltstr.substring (posição - comprimento do word, posição); } // comece a cortar a string do comprimento especificado da posição atual // word = spiltstr.substring (posição, posição + wordLength); // Se não houver cortes no dicionário de particípio da palavra, descarte um personagem enquanto (! Map.containsKey (word)) {// se for uma única palavra, saia do loop if (word.length () == 1) {// se for uma letra ou número, divide as letras contínuas ou os números se if (word.matches ("a-za-ze-za (a-Z) (se forem), se forem uma letra ou número de letrias ou números contínuos. Loop diretamente para adicionar os caracteres contínuos subsequentes se (lefttoright) {for (int i = spiltstr.indexOf (word, position)+1; i <spiltstr .Length (); i ++) {if ((spiltstr.Charat (i)> = '0' && spilsT.Charat (i) <= 9 ') SpiltStr .Charat (i) <= 'Z') || } mais quebrar; }} else {// Se for uma correspondência reversa, adicione e vire os números contínuos e os caracteres alfabéticos antes da posição atual para (int i = spiltstr.indexOf (word, posição - 1) - 1; i> = 0; i-) {if ((spiltstr.charat (i)> = '0' && sluts.ats.ats.athats. (s) (i) - ') = 0; (spiltstr.charat (i)> = 'a' && spiltstr.charat (i) <= 'z') || (spiltstr.charat (i)> = 'a' && spiltstr.charat (i) <= 'z') {word += spiltstr.charat (i); if (i == 0) {stringbuffer sb = new StringBuffer (word); word = sb.ververse (). ToString (); }} else {// flip operação stringbuffer sb = new StringBuffer (word); word = sb.ververse (). ToString (); quebrar; } } } } quebrar; } // Se for uma correspondência máxima para a frente, descarte o último caractere if (lefttoright) word = word.substring (0, word.length () - 1); // descarte o primeiro personagem else Word = word.substring (1); } // Salvar a sequência dividida na tabela especificada se (lefttoright) palavras de esquerda.add (word); else stronTwords.add (word); // strings processados adicionam comprimento += word.length (); } // Se for uma correspondência máxima inversa, ajuste a string na tabela para encaminhar if (! Lefttoright) {for (int i = stronTwords.size ()-1; i> = 0; i-) {lesftwords.add (s DEMTERWWORDS.GET.get (i)); }} // Retorna o resultado do resultado retornar as palavras de esquerda; } / ** * Determine se os dois conjuntos são iguais * * @param list1 * set 1 * @param list2 * set 2 * @return return true se for igual, caso contrário false * / public boolean isequal (list <string> list1, list <string> list2) {if (list1.isempty () && list2.isempty ()) return); if (list1.size ()! = list2.size ()) retornar false; for (int i = 0; i <list1.size (); i ++) {if (! list1.get (i) .equals (list2.get (i))) retornar false; } retornar true; } / *** Função de ambiguidade do particípio discriminante** @param inputStr* string a ser dividido* @return partition resultado* / list public <string> resultadoword (string inputStr) {// Lista de resultados da partição <tring> resultado = new ArrayList <string> (); // Lista de resultados do particípio "Snake Snake" <ScorrerLeft = new ArrayList <String> (); // "Snake Medike" (parte divergente) Lista de resultados de particípio <string> resultMiddle = new ArrayList <String> (); // Lista de resultados do particípio "Snake Right Snake" <strultRright = new ArrayList <String> (); // Avançar a lista de resultados de segmentação de palavras máximos de correspondência <flest = new ArrayList <String> (); // Lista de resultados de segmentação de palavras com correspondência máxima inversa <String> Right = new ArrayList <String> (); esquerda = derramado (inputStr, true); /*System.out.println("forward Particle Result: "); for (string string: esquerda) {System.out.print (string + "/"); } System.out.println ("/n Particle Inverse Result:"); */ direita = derramado (inputStr, false); /*para (string string: direita) {System.out.print (string + "/"); } System.out.println ("/ nboth-way Particle Result:");*/ // // Determine se a palavra particípio de particípio em ambas as extremidades se cruzou no meio da sequência de entrada. Enquanto não houver interseção, ele continua em loop enquanto (esquerda.get (0) .Length () + Right.get (right.size () - 1) .Length () <inputStr .Length ()) {// Se os resultados da esquerda e da palavra reversa forem iguais, o resultado direto »salvará para fora do loop se (esquerda (esquerda e reverso, o resultado), o resultado para a frente) saltará para fora; quebrar; } // Se os resultados do particípio de palavra direto e reversa forem diferentes, então aquele com o menor número de particípios é obtido, e não há necessidade de fazer loop se (left.size ()! Esquerda: direita; quebrar; } // Se as condições acima não forem atendidas, implemente o algoritmo "Snake" // deixe "Esquerda Gananciosa", coma a primeira palavra da palavra para frente Particle Resultleft.add (esquerd.get (0)); // Deixe "Snake Gananciosa Right" coma a última palavra do resultado do particípio reverso Resultright.add (Right.get (right.size () - 1)); // Remova as palavras comidas por "Snake" inputStr = inputStr.substring (esquerd.get (0) .Length ()); inputStr = inputStr.substring (0, inputStr.Length () - Right.get (right.size () - 1) .Length ()); // Limpe os resultados anteriores de segmentação positiva e reversa de palavras para impedir a interferência esquerda.Clear (); Right.Clear (); // Inicie o particípio para que não conspirem as cordas esquerdas = derramadas (inputStr, true); direita = derramado (inputStr, false); } // O final do loop significa que o particípio não é ambíguo, ou a "cobra gananciosa" come de ambas as extremidades para o cruzamento // se for a palavra particípio no cruzamento, o seguinte julgamento deve ser feito: // se o interseção do meio (left.get (0) .Length () + Right.get (right.size () - 1) .Length ()> inputStr .Length ()) resultMiddle = esquerda; / // se a interseção do meio se cruzar, apenas leva a comida e não há sobreposição: // O primeiro particípio na direção para a frente + o comprimento do último particípio na direção reversa = insira o comprimento total da string, então a direção da frente e da direita) pode ser escrita. resultmiddle.add (esquerda.get (0)); resultmiddle.add (right.get (right.size () - 1)); } // Adicione o resultado do particípio inequívoco ao resultado final para (String String: ResultLeft) {Result.add (String); } para (String String: ResultMiddle) {Result.add (String); } // O particípio armazenado em "Snake Ganancioso Right" deve ser ajustado para encaminhar para (int i = resultright.size ()-1; i> = 0; i-) {resultado.add (resultright.get (i)); } resultado de retorno; } / ** * Divida um parágrafo em várias frases e execute a segmentação de palavras separadamente * * @param inputStr * Um parágrafo a ser dividido * @return Participe resultado deste parágrafo * / list public <string> Resultadospilt (string inputStr) {// usado para armazenar o resultado final do segmento de palavras <strider = resultado; // Se a pontuação for encontrada, ela será dividida em várias frases String regex = "[,.;!?]"; String [] st = inputStr.split (regex); // Adicione o resultado do particípio de cada frase ao resultado final do particípio para (String Stri: ST) {List <String> list = ResultWord (STRI); resultado.addall (lista); } resultado de retorno; } public static void main (string [] args) {// Exemplo: venha ver se o preço da casa é caro? Tênis de tênis de tênis scanner de entrada = new scanner (system.in); String str = input.NextLine (); Wordspilt wordspilt = null; tente {wordspilt = new wordspilt (); } catch (ioexception e) {e.printStackTrace (); } Lista <String> list = wordspilt.resultword (str); para (String String: List) {System.out.print (String + "/"); }}}O src/dict.txt é um arquivo de dicionário, e as configurações são as seguintes:
Bem -vindo ao script do Wolin.com Download de scripts download de material do script
Os resultados da operação são os seguintes:
Para obter mais informações sobre os algoritmos Java, os leitores interessados neste site podem visualizar os tópicos: "Estrutura de dados Java e tutorial de algoritmo", "Resumo das dicas de nó da operação Java Dom", "Resumo de dicas de operação de Java e Operação de Java" e "Resumo de Java cache" Tips "TIPS"
Espero que este artigo seja útil para a programação Java de todos.