Showing preview only (2,967K chars total). Download the full file or copy to clipboard to get everything.
Repository: magese/ik-analyzer-solr7
Branch: master
Commit: f0059e2c78d8
Files: 38
Total size: 21.4 MB
Directory structure:
gitextract_7eqaxw1n/
├── .github/
│ └── ISSUE_TEMPLATE/
│ └── bug_report.md
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README-CLOUD.md
├── README.md
├── pom.xml
└── src/
└── main/
├── java/
│ └── org/
│ └── wltea/
│ └── analyzer/
│ ├── cfg/
│ │ ├── Configuration.java
│ │ └── DefaultConfig.java
│ ├── core/
│ │ ├── AnalyzeContext.java
│ │ ├── CJKSegmenter.java
│ │ ├── CN_QuantifierSegmenter.java
│ │ ├── CharacterUtil.java
│ │ ├── IKArbitrator.java
│ │ ├── IKSegmenter.java
│ │ ├── ISegmenter.java
│ │ ├── LetterSegmenter.java
│ │ ├── Lexeme.java
│ │ ├── LexemePath.java
│ │ └── QuickSortSet.java
│ ├── dic/
│ │ ├── DictSegment.java
│ │ ├── Dictionary.java
│ │ └── Hit.java
│ ├── lucene/
│ │ ├── IKAnalyzer.java
│ │ ├── IKTokenizer.java
│ │ ├── IKTokenizerFactory.java
│ │ └── UpdateThread.java
│ └── query/
│ ├── IKQueryExpressionParser.java
│ └── SWMCQueryBuilder.java
└── resources/
├── IKAnalyzer.cfg.xml
├── dict/
│ ├── main2012.dic
│ ├── main_dic_2020.dic
│ └── quantifier.dic
├── dynamicdic.txt
├── ext.dic
├── ik.conf
└── stopword.dic
================================================
FILE CONTENTS
================================================
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
================================================
FILE: .gitignore
================================================
*.bak
*.class
*.log
.classpath
.project
.settings
target
.idea
*.iml
================================================
FILE: .travis.yml
================================================
language: java
jdk:
- openjdk8
================================================
FILE: CONTRIBUTING.md
================================================
================================================
FILE: LICENSE
================================================
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
10.You are not allowed to remove or modify any donation links/images in
this project, otherwise we will reclaim all authorization.
11.You're free to use this software at your own/you company/your orgnization 's
use. BUT You don't have the permission to sell the copy or the
redistribution of this software to others in any form.
12.If you've forked this project, you must use the same lisence.
END OF TERMS AND CONDITIONS
Copyright 2018 Magese magese@live.cn
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
================================================
FILE: README-CLOUD.md
================================================
## Solr-Cloud说明
##### 因为`Solr-Cloud`中的配置文件是交由`zookeeper`进行管理的, 所以为了方便更新动态词典, 所以也要将动态词典文件上传至`zookeeper`中,目录与`solr`的配置文件目录一致。
#### 注意:因为`zookeeper`中的配置文件大小不能超过`1m`,当词典列表过多时,需将词典文件切分成多个。
1. 将jar包放入每台服务器的Solr服务的`Jetty`或`Tomcat`的`webapp/WEB-INF/lib/`目录下;
2. 将`resources`目录下的`IKAnalyzer.cfg.xml`、`ext.dic`、`stopword.dic`放入solr服务的`Jetty`或`Tomcat`的`webapp/WEB-INF/classes/`目录下;
```console
① IKAnalyzer.cfg.xml (IK默认的配置文件,用于配置自带的扩展词典及停用词典)
② ext.dic (默认的扩展词典)
③ stopword.dic (默认的停词词典)
```
注意:与单机版不同,`ik.conf`及`dynamicdic.txt`请不要放在`classes`目录下!
3. 将`resources`目录下的`ik.conf`及`dynamicdic.txt`放入solr配置文件夹中,与solr的`managed-schema`文件同目录中;
```console
① ik.conf (动态词典配置文件)
files (动态词典列表,可以设置多个词典表,用逗号进行分隔,默认动态词典表为dynamicdic.txt)
lastupdate (默认值为0,每次对动态词典表修改后请修改该值,必须大于上次的值,不然不会将词典表中新的词语添加到内存中。)
② dynamicdic.txt (默认的动态词典,在此文件配置的词语不需重启服务即可加载进内存中。以#开头的词语视为注释,将不会加载到内存中。)
```
4. 配置Solr的`managed-schema`,添加`ik分词器`,示例如下;
```xml
<!-- ik分词器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
```
5. 将配置文件上传至`zookeeper`中,首次使用请重启服务或reload Collection。
6. 测试分词:
* 此时的动态词典文件为空

* 配置文件lastupdate为0

* 测试分词

7. 测试动态词典:
* 增加动态词典词语并上传至`zookeeper`

* 修改配置文件并上传至`zookeeper`

* 测试分词

================================================
FILE: README.md
================================================
# ik-analyzer-solr
ik-analyzer for solr 7.x-8.x
<!-- Badges section here. -->
[](https://search.maven.org/search?q=g:com.github.magese%20AND%20a:ik-analyzer&core=gav)
[](https://github.com/magese/ik-analyzer-solr/releases)
[](./LICENSE)
[](https://travis-ci.org/magese/ik-analyzer-solr)
[](https://github.com/magese/ik-analyzer-solr/network/members)
[](https://github.com/magese/ik-analyzer-solr/stargazers)
<!-- /Badges section end. -->
## 简介
**适配最新版本solr 7&8;**
**扩展IK原有词库:**
| 分词工具 | 词库中词的数量 | 最后更新时间 |
| :------: | :------: | :------: |
| ik | 27.5万 | 2012年 |
| mmseg | 15.7万 | 2017年 |
| word | 64.2万 | 2014年 |
| jieba | 58.4万 | 2012年 |
| jcesg | 16.6万 | 2018年 |
| sougou词库 | 115.2万 | 2020年 |
**将以上词库进行整理后约187.1万条词汇;**
**添加动态加载词典表功能,在不需要重启solr服务的情况下加载新增的词典。**
> <small>关闭默认主词典请在`IKAnalyzer.cfg.xml`配置文件中设置`use_main_dict`为`false`。</small>
> * IKAnalyzer的原作者为林良益<linliangyi2007@gmail.com>,项目网站为<http://code.google.com/p/ik-analyzer>
> * 该项目动态加载功能根据博主[@星火燎原智勇](http://www.cnblogs.com/liang1101/articles/6395016.html)的博客进行修改,其GITHUB地址为[@liang68](https://github.com/liang68)
## 使用说明
* jar包下载地址:[](https://search.maven.org/remotecontent?filepath=com/github/magese/ik-analyzer/8.5.0/ik-analyzer-8.5.0.jar)
* 历史版本:[](https://search.maven.org/search?q=g:com.github.magese%20AND%20a:ik-analyzer&core=gav)
```xml
<!-- Maven仓库地址 -->
<dependency>
<groupId>com.github.magese</groupId>
<artifactId>ik-analyzer</artifactId>
<version>8.5.0</version>
</dependency>
```
### Solr-Cloud
* [Solr-Cloud说明](./README-CLOUD.md)
### 单机版Solr
1. 将jar包放入Solr服务的`Jetty`或`Tomcat`的`webapp/WEB-INF/lib/`目录下;
2. 将`resources`目录下的5个配置文件放入solr服务的`Jetty`或`Tomcat`的`webapp/WEB-INF/classes/`目录下;
```console
① IKAnalyzer.cfg.xml
② ext.dic
③ stopword.dic
④ ik.conf
⑤ dynamicdic.txt
```
3. 配置Solr的`managed-schema`,添加`ik分词器`,示例如下;
```xml
<!-- ik分词器 -->
<fieldType name="text_ik" class="solr.TextField">
<analyzer type="index">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="false" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="org.wltea.analyzer.lucene.IKTokenizerFactory" useSmart="true" conf="ik.conf"/>
<filter class="solr.LowerCaseFilterFactory"/>
</analyzer>
</fieldType>
```
4. 启动Solr服务测试分词;

5. `IKAnalyzer.cfg.xml`配置文件说明:
| 名称 | 类型 | 描述 | 默认 |
| ------ | ------ | ------ | ------ |
| use_main_dict | boolean | 是否使用默认主词典 | true |
| ext_dict | String | 扩展词典文件名称,多个用分号隔开 | ext.dic; |
| ext_stopwords | String | 停用词典文件名称,多个用分号隔开 | stopword.dic; |
6. `ik.conf`文件说明:
```properties
files=dynamicdic.txt
lastupdate=0
```
1. `files`为动态词典列表,可以设置多个词典表,用逗号进行分隔,默认动态词典表为`dynamicdic.txt`;
2. `lastupdate`默认值为`0`,每次对动态词典表修改后请+1,不然不会将词典表中新的词语添加到内存中。<s>`lastupdate`采用的是`int`类型,不支持时间戳,如果使用时间戳的朋友可以把源码中的`int`改成`long`即可;</s> `2018-08-23` 已将源码中`lastUpdate`改为`long`类型,现可以用时间戳了。
7. `dynamicdic.txt` 为动态词典
在此文件配置的词语不需重启服务即可加载进内存中。
以`#`开头的词语视为注释,将不会加载到内存中。
## 更新说明
- **2021-12-23:** 升级lucene版本为`8.5.0`
- **2021-03-22:** 升级lucene版本为`8.4.0`
- **2020-12-30:**
- 升级lucene版本为`8.3.1`
- 更新词库
- **2019-11-12:**
- 升级lucene版本为`8.3.0`
- `IKAnalyzer.cfg.xml`增加配置项`use_main_dict`,用于配置是否启用默认主词典
- **2019-09-27:** 升级lucene版本为`8.2.0`
- **2019-07-11:** 升级lucene版本为`8.1.1`
- **2019-05-27:**
- 升级lucene版本为`8.1.0`
- 优化原词典部分重复词语
- 更新搜狗2019最新流行词汇词典,约20k词汇量
- **2019-05-15:** 升级lucene版本为`8.0.0`,并支持Solr8使用
- **2019-03-01:** 升级lucene版本为`7.7.1`
- **2019-02-15:** 升级lucene版本为`7.7.0`
- **2018-12-26:**
- 升级lucene版本为`7.6.0`
- 兼容solr-cloud,动态词典配置文件及动态词典可交由`zookeeper`进行管理
- 动态词典增加注释功能,以`#`开头的行将视为注释
- **2018-12-04:** 整理更新词库列表`magese.dic`
- **2018-10-10:** 升级lucene版本为`7.5.0`
- **2018-09-03:** 优化注释与输出信息,取消部分中文输出避免不同字符集乱码,现会打印被调用inform方法的hashcode
- **2018-08-23:**
- 完善了动态更新词库代码注释;
- 将ik.conf配置文件中的lastUpdate属性改为long类型,现已支持时间戳形式
- **2018-08-13:** 更新maven仓库地址
- **2018-08-01:** 移除默认的扩展词与停用词
- **2018-07-23:** 升级lucene版本为`7.4.0`
## 感谢 Thanks
[](https://www.jetbrains.com/?from=ik-analyzer-solr)
[](https://www.java.com)
## BUG & 疑问 & 其它
如果您在使用过程中遇到了BUG,或者有不清楚的地方,请挂ISSUE或者联系作者:<magese@live.cn>
如果您觉得该项目对您有帮助,请别忘记给这个项目一个`star`
================================================
FILE: pom.xml
================================================
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.magese</groupId>
<artifactId>ik-analyzer</artifactId>
<version>8.5.0</version>
<packaging>jar</packaging>
<name>ik-analyzer-solr</name>
<url>http://code.google.com/p/ik-analyzer/</url>
<description>IK-Analyzer for solr 7-8</description>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<lucene.version>8.5.0</lucene.version>
<javac.src.version>1.8</javac.src.version>
<javac.target.version>1.8</javac.target.version>
<maven.compiler.plugin.version>3.3</maven.compiler.plugin.version>
</properties>
<dependencies>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-core</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-queryparser</artifactId>
<version>${lucene.version}</version>
</dependency>
<dependency>
<groupId>org.apache.lucene</groupId>
<artifactId>lucene-analyzers-common</artifactId>
<version>${lucene.version}</version>
</dependency>
</dependencies>
<licenses>
<license>
<name>The Apache Software License, Version 2.0</name>
<url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
<distribution>repo</distribution>
</license>
</licenses>
<scm>
<tag>master</tag>
<url>https://github.com/magese/ik-analyzer-solr</url>
<connection>scm:git:git@github.com:magese/ik-analyzer-solr.git</connection>
<developerConnection>scm:git:git@github.com:magese/ik-analyzer-solr.git</developerConnection>
</scm>
<developers>
<developer>
<name>magese</name>
<email>magese@live.cn</email>
</developer>
</developers>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<configuration>
<source>${javac.src.version}</source>
<target>${javac.src.version}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<configuration>
<aggregate>true</aggregate>
</configuration>
</plugin>
</plugins>
<defaultGoal>compile</defaultGoal>
</build>
<profiles>
<profile>
<id>release</id>
<distributionManagement>
<snapshotRepository>
<id>oss</id>
<url>https://oss.sonatype.org/content/repositories/snapshots/</url>
</snapshotRepository>
<repository>
<id>oss</id>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
</distributionManagement>
<build>
<plugins>
<!-- Source -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.0.1</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Javadoc -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.10.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Gpg Signature -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
================================================
FILE: src/main/java/org/wltea/analyzer/cfg/Configuration.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.cfg;
import java.util.List;
/**
* 配置管理类接口
*/
public interface Configuration {
/**
* 返回useSmart标志位
* useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
*
* @return useSmart
*/
boolean useSmart();
/**
* 设置useSmart标志位
*
* @param useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
*/
void setUseSmart(boolean useSmart);
/**
* 获取是否使用主词典
*
* @return = true 默认加载主词典, = false 不加载主词典
*/
boolean useMainDict();
/**
* 设置是否使用主词典
*
* @param useMainDic = true 默认加载主词典, = false 不加载主词典
*/
void setUseMainDict(boolean useMainDic);
/**
* 获取主词典路径
*
* @return String 主词典路径
*/
String getMainDictionary();
/**
* 获取量词词典路径
*
* @return String 量词词典路径
*/
String getQuantifierDictionary();
/**
* 获取扩展字典配置路径
*
* @return 相对类加载器的路径
*/
List<String> getExtDictionarys();
/**
* 获取扩展停止词典配置路径
*
* @return 相对类加载器的路径
*/
List<String> getExtStopWordDictionarys();
}
================================================
FILE: src/main/java/org/wltea/analyzer/cfg/DefaultConfig.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.cfg;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;
/**
* Configuration 默认实现
*/
public class DefaultConfig implements Configuration {
/*
* 分词器默认字典路径
*/
private static final String PATH_DIC_MAIN = "dict/main_dic_2020.dic";
private static final String PATH_DIC_QUANTIFIER = "dict/quantifier.dic";
/*
* 分词器配置文件路径
*/
private static final String FILE_NAME = "IKAnalyzer.cfg.xml";
// 配置属性——是否使用主词典
private static final String USE_MAIN = "use_main_dict";
// 配置属性——扩展字典
private static final String EXT_DICT = "ext_dict";
// 配置属性——扩展停止词典
private static final String EXT_STOP = "ext_stopwords";
private final Properties props;
// 是否使用smart方式分词
private boolean useSmart;
// 是否加载主词典
private boolean useMainDict = true;
/**
* 返回单例
*
* @return Configuration单例
*/
public static Configuration getInstance() {
return new DefaultConfig();
}
/*
* 初始化配置文件
*/
private DefaultConfig() {
props = new Properties();
InputStream input = this.getClass().getClassLoader().getResourceAsStream(FILE_NAME);
if (input != null) {
try {
props.loadFromXML(input);
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 返回useSmart标志位
* useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
*
* @return useSmart
*/
public boolean useSmart() {
return useSmart;
}
/**
* 设置useSmart标志位
*
* @param useSmart =true ,分词器使用智能切分策略, =false则使用细粒度切分
*/
@Override
public void setUseSmart(boolean useSmart) {
this.useSmart = useSmart;
}
/**
* 获取是否使用主词典
*
* @return = true 默认加载主词典, = false 不加载主词典
*/
public boolean useMainDict() {
String useMainDictCfg = props.getProperty(USE_MAIN);
if (useMainDictCfg != null && useMainDictCfg.trim().length() > 0)
setUseMainDict(Boolean.parseBoolean(useMainDictCfg));
return useMainDict;
}
/**
* 设置是否使用主词典
*
* @param useMainDict = true 默认加载主词典, = false 不加载主词典
*/
@Override
public void setUseMainDict(boolean useMainDict) {
this.useMainDict = useMainDict;
}
/**
* 获取主词典路径
*
* @return String 主词典路径
*/
public String getMainDictionary() {
return PATH_DIC_MAIN;
}
/**
* 获取量词词典路径
*
* @return String 量词词典路径
*/
public String getQuantifierDictionary() {
return PATH_DIC_QUANTIFIER;
}
/**
* 获取扩展字典配置路径
*
* @return 相对类加载器的路径
*/
public List<String> getExtDictionarys() {
List<String> extDictFiles = new ArrayList<>(2);
String extDictCfg = props.getProperty(EXT_DICT);
if (extDictCfg != null) {
//使用;分割多个扩展字典配置
String[] filePaths = extDictCfg.split(";");
for (String filePath : filePaths) {
if (filePath != null && !"".equals(filePath.trim())) {
extDictFiles.add(filePath.trim());
}
}
}
return extDictFiles;
}
/**
* 获取扩展停止词典配置路径
*
* @return 相对类加载器的路径
*/
public List<String> getExtStopWordDictionarys() {
List<String> extStopWordDictFiles = new ArrayList<>(2);
String extStopWordDictCfg = props.getProperty(EXT_STOP);
if (extStopWordDictCfg != null) {
//使用;分割多个扩展字典配置
String[] filePaths = extStopWordDictCfg.split(";");
for (String filePath : filePaths) {
if (filePath != null && !"".equals(filePath.trim())) {
extStopWordDictFiles.add(filePath.trim());
}
}
}
return extStopWordDictFiles;
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/AnalyzeContext.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.dic.Dictionary;
import java.io.IOException;
import java.io.Reader;
import java.util.*;
/**
* 分词器上下文状态
*/
class AnalyzeContext {
// 默认缓冲区大小
private static final int BUFF_SIZE = 4096;
// 缓冲区耗尽的临界值
private static final int BUFF_EXHAUST_CRITICAL = 100;
// 字符窜读取缓冲
private char[] segmentBuff;
// 字符类型数组
private int[] charTypes;
// 记录Reader内已分析的字串总长度
// 在分多段分析词元时,该变量累计当前的segmentBuff相对于reader起始位置的位移
private int buffOffset;
// 当前缓冲区位置指针
private int cursor;
// 最近一次读入的,可处理的字串长度
private int available;
// 子分词器锁
// 该集合非空,说明有子分词器在占用segmentBuff
private final Set<String> buffLocker;
// 原始分词结果集合,未经歧义处理
private QuickSortSet orgLexemes;
// LexemePath位置索引表
private final Map<Integer, LexemePath> pathMap;
// 最终分词结果集
private final LinkedList<Lexeme> results;
// 分词器配置项
private final Configuration cfg;
AnalyzeContext(Configuration cfg) {
this.cfg = cfg;
this.segmentBuff = new char[BUFF_SIZE];
this.charTypes = new int[BUFF_SIZE];
this.buffLocker = new HashSet<>();
this.orgLexemes = new QuickSortSet();
this.pathMap = new HashMap<>();
this.results = new LinkedList<>();
}
int getCursor() {
return this.cursor;
}
char[] getSegmentBuff() {
return this.segmentBuff;
}
char getCurrentChar() {
return this.segmentBuff[this.cursor];
}
int getCurrentCharType() {
return this.charTypes[this.cursor];
}
int getBufferOffset() {
return this.buffOffset;
}
/**
* 根据context的上下文情况,填充segmentBuff
*
* @param reader 读取流
* @return 返回待分析的(有效的)字串长度
*/
int fillBuffer(Reader reader) throws IOException {
int readCount = 0;
if (this.buffOffset == 0) {
// 首次读取reader
readCount = reader.read(segmentBuff);
} else {
int offset = this.available - this.cursor;
if (offset > 0) {
// 最近一次读取的>最近一次处理的,将未处理的字串拷贝到segmentBuff头部
System.arraycopy(this.segmentBuff, this.cursor, this.segmentBuff, 0, offset);
readCount = offset;
}
// 继续读取reader ,以onceReadIn - onceAnalyzed为起始位置,继续填充segmentBuff剩余的部分
readCount += reader.read(this.segmentBuff, offset, BUFF_SIZE - offset);
}
// 记录最后一次从Reader中读入的可用字符长度
this.available = readCount;
// 重置当前指针
this.cursor = 0;
return readCount;
}
/**
* 初始化buff指针,处理第一个字符
*/
void initCursor() {
this.cursor = 0;
this.segmentBuff[this.cursor] = CharacterUtil.regularize(this.segmentBuff[this.cursor]);
this.charTypes[this.cursor] = CharacterUtil.identifyCharType(this.segmentBuff[this.cursor]);
}
/**
* 指针+1
* 成功返回 true; 指针已经到了buff尾部,不能前进,返回false
* 并处理当前字符
*/
boolean moveCursor() {
if (this.cursor < this.available - 1) {
this.cursor++;
this.segmentBuff[this.cursor] = CharacterUtil.regularize(this.segmentBuff[this.cursor]);
this.charTypes[this.cursor] = CharacterUtil.identifyCharType(this.segmentBuff[this.cursor]);
return true;
} else {
return false;
}
}
/**
* 设置当前segmentBuff为锁定状态
* 加入占用segmentBuff的子分词器名称,表示占用segmentBuff
*/
void lockBuffer(String segmenterName) {
this.buffLocker.add(segmenterName);
}
/**
* 移除指定的子分词器名,释放对segmentBuff的占用
*/
void unlockBuffer(String segmenterName) {
this.buffLocker.remove(segmenterName);
}
/**
* 只要buffLocker中存在segmenterName
* 则buffer被锁定
*
* @return boolean 缓冲去是否被锁定
*/
private boolean isBufferLocked() {
return this.buffLocker.size() > 0;
}
/**
* 判断当前segmentBuff是否已经用完
* 当前执针cursor移至segmentBuff末端this.available - 1
*/
boolean isBufferConsumed() {
return this.cursor == this.available - 1;
}
/**
* 判断segmentBuff是否需要读取新数据
* <p>
* 满足一下条件时,
* 1.available == BUFF_SIZE 表示buffer满载
* 2.buffIndex < available - 1 && buffIndex > available - BUFF_EXHAUST_CRITICAL表示当前指针处于临界区内
* 3.!context.isBufferLocked()表示没有segmenter在占用buffer
* 要中断当前循环(buffer要进行移位,并再读取数据的操作)
*/
boolean needRefillBuffer() {
return this.available == BUFF_SIZE
&& this.cursor < this.available - 1
&& this.cursor > this.available - BUFF_EXHAUST_CRITICAL
&& !this.isBufferLocked();
}
/**
* 累计当前的segmentBuff相对于reader起始位置的位移
*/
void markBufferOffset() {
this.buffOffset += this.cursor;
}
/**
* 向分词结果集添加词元
*
* @param lexeme 词元
*/
void addLexeme(Lexeme lexeme) {
this.orgLexemes.addLexeme(lexeme);
}
/**
* 添加分词结果路径
* 路径起始位置 ---> 路径 映射表
*
* @param path 分词结果路径
*/
void addLexemePath(LexemePath path) {
if (path != null) {
this.pathMap.put(path.getPathBegin(), path);
}
}
/**
* 返回原始分词结果
*/
QuickSortSet getOrgLexemes() {
return this.orgLexemes;
}
/**
* 推送分词结果到结果集合
* 1.从buff头部遍历到this.cursor已处理位置
* 2.将map中存在的分词结果推入results
* 3.将map中不存在的CJDK字符以单字方式推入results
*/
void outputToResult() {
int index = 0;
while (index <= this.cursor) {
// 跳过非CJK字符
if (CharacterUtil.CHAR_USELESS == this.charTypes[index]) {
index++;
continue;
}
// 从pathMap找出对应index位置的LexemePath
LexemePath path = this.pathMap.get(index);
if (path != null) {
// 输出LexemePath中的lexeme到results集合
Lexeme l = path.pollFirst();
while (l != null) {
this.results.add(l);
// 将index移至lexeme后
index = l.getBegin() + l.getLength();
l = path.pollFirst();
if (l != null) {
// 输出path内部,词元间遗漏的单字
for (; index < l.getBegin(); index++) {
this.outputSingleCJK(index);
}
}
}
} else {// pathMap中找不到index对应的LexemePath
// 单字输出
this.outputSingleCJK(index);
index++;
}
}
// 清空当前的Map
this.pathMap.clear();
}
/**
* 对CJK字符进行单字输出
*
* @param index 字符索引
*/
private void outputSingleCJK(int index) {
if (CharacterUtil.CHAR_CHINESE == this.charTypes[index]) {
Lexeme singleCharLexeme = new Lexeme(this.buffOffset, index, 1, Lexeme.TYPE_CNCHAR);
this.results.add(singleCharLexeme);
} else if (CharacterUtil.CHAR_OTHER_CJK == this.charTypes[index]) {
Lexeme singleCharLexeme = new Lexeme(this.buffOffset, index, 1, Lexeme.TYPE_OTHER_CJK);
this.results.add(singleCharLexeme);
}
}
/**
* 返回lexeme
* <p>
* 同时处理合并
*/
Lexeme getNextLexeme() {
// 从结果集取出,并移除第一个Lexme
Lexeme result = this.results.pollFirst();
while (result != null) {
// 数量词合并
this.compound(result);
if (Dictionary.getSingleton().isStopWord(this.segmentBuff, result.getBegin(), result.getLength())) {
// 是停止词继续取列表的下一个
result = this.results.pollFirst();
} else {
// 不是停止词, 生成lexeme的词元文本,输出
result.setLexemeText(String.valueOf(segmentBuff, result.getBegin(), result.getLength()));
break;
}
}
return result;
}
/**
* 重置分词上下文状态
*/
void reset() {
this.buffLocker.clear();
this.orgLexemes = new QuickSortSet();
this.available = 0;
this.buffOffset = 0;
this.charTypes = new int[BUFF_SIZE];
this.cursor = 0;
this.results.clear();
this.segmentBuff = new char[BUFF_SIZE];
this.pathMap.clear();
}
/**
* 组合词元
*/
private void compound(Lexeme result) {
if (!this.cfg.useSmart()) {
return;
}
// 数量词合并处理
if (!this.results.isEmpty()) {
if (Lexeme.TYPE_ARABIC == result.getLexemeType()) {
Lexeme nextLexeme = this.results.peekFirst();
boolean appendOk = false;
if (nextLexeme != null) {
if (Lexeme.TYPE_CNUM == nextLexeme.getLexemeType()) {
// 合并英文数词+中文数词
appendOk = result.append(nextLexeme, Lexeme.TYPE_CNUM);
} else if (Lexeme.TYPE_COUNT == nextLexeme.getLexemeType()) {
// 合并英文数词+中文量词
appendOk = result.append(nextLexeme, Lexeme.TYPE_CQUAN);
}
}
if (appendOk) {
// 弹出
this.results.pollFirst();
}
}
// 可能存在第二轮合并
if (Lexeme.TYPE_CNUM == result.getLexemeType() && !this.results.isEmpty()) {
Lexeme nextLexeme = this.results.peekFirst();
boolean appendOk = false;
if (Lexeme.TYPE_COUNT == nextLexeme.getLexemeType()) {
// 合并中文数词+中文量词
appendOk = result.append(nextLexeme, Lexeme.TYPE_CQUAN);
}
if (appendOk) {
// 弹出
this.results.pollFirst();
}
}
}
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/CJKSegmenter.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
import org.wltea.analyzer.dic.Dictionary;
import org.wltea.analyzer.dic.Hit;
import java.util.LinkedList;
import java.util.List;
/**
* 中文-日韩文子分词器
*/
class CJKSegmenter implements ISegmenter {
// 子分词器标签
private static final String SEGMENTER_NAME = "CJK_SEGMENTER";
// 待处理的分词hit队列
private final List<Hit> tmpHits;
CJKSegmenter() {
this.tmpHits = new LinkedList<>();
}
/* (non-Javadoc)
* @see org.wltea.analyzer.core.ISegmenter#analyze(org.wltea.analyzer.core.AnalyzeContext)
*/
public void analyze(AnalyzeContext context) {
if (CharacterUtil.CHAR_USELESS != context.getCurrentCharType()) {
// 优先处理tmpHits中的hit
if (!this.tmpHits.isEmpty()) {
// 处理词段队列
Hit[] tmpArray = this.tmpHits.toArray(new Hit[0]);
for (Hit hit : tmpArray) {
hit = Dictionary.getSingleton().matchWithHit(context.getSegmentBuff(), context.getCursor(), hit);
if (hit.isMatch()) {
// 输出当前的词
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), hit.getBegin(), context.getCursor() - hit.getBegin() + 1, Lexeme.TYPE_CNWORD);
context.addLexeme(newLexeme);
if (!hit.isPrefix()) {// 不是词前缀,hit不需要继续匹配,移除
this.tmpHits.remove(hit);
}
} else if (hit.isUnmatch()) {
// hit不是词,移除
this.tmpHits.remove(hit);
}
}
}
// *********************************
// 再对当前指针位置的字符进行单字匹配
Hit singleCharHit = Dictionary.getSingleton().matchInMainDict(context.getSegmentBuff(), context.getCursor(), 1);
// 首字为词前缀
if (singleCharHit.isMatch()) {
// 输出当前的词
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), context.getCursor(), 1, Lexeme.TYPE_CNWORD);
context.addLexeme(newLexeme);
}
// 前缀匹配则放入hit列表
if (singleCharHit.isPrefix()) {
// 前缀匹配则放入hit列表
this.tmpHits.add(singleCharHit);
}
} else {
// 遇到CHAR_USELESS字符
// 清空队列
this.tmpHits.clear();
}
// 判断缓冲区是否已经读完
if (context.isBufferConsumed()) {
// 清空队列
this.tmpHits.clear();
}
// 判断是否锁定缓冲区
if (this.tmpHits.size() == 0) {
context.unlockBuffer(SEGMENTER_NAME);
} else {
context.lockBuffer(SEGMENTER_NAME);
}
}
/* (non-Javadoc)
* @see org.wltea.analyzer.core.ISegmenter#reset()
*/
public void reset() {
// 清空队列
this.tmpHits.clear();
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/CN_QuantifierSegmenter.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
import org.wltea.analyzer.dic.Dictionary;
import org.wltea.analyzer.dic.Hit;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;
/**
* 中文数量词子分词器
*/
class CN_QuantifierSegmenter implements ISegmenter {
// 子分词器标签
private static final String SEGMENTER_NAME = "QUAN_SEGMENTER";
private static final Set<Character> CHN_NUMBER_CHARS = new HashSet<>();
static {
// 中文数词
String chn_Num = "一二两三四五六七八九十零壹贰叁肆伍陆柒捌玖拾百千万亿拾佰仟萬億兆卅廿";
char[] ca = chn_Num.toCharArray();
for (char nChar : ca) {
CHN_NUMBER_CHARS.add(nChar);
}
}
/*
* 词元的开始位置,
* 同时作为子分词器状态标识
* 当start > -1 时,标识当前的分词器正在处理字符
*/
private int nStart;
/*
* 记录词元结束位置
* end记录的是在词元中最后一个出现的合理的数词结束
*/
private int nEnd;
// 待处理的量词hit队列
private final List<Hit> countHits;
CN_QuantifierSegmenter() {
nStart = -1;
nEnd = -1;
this.countHits = new LinkedList<>();
}
/**
* 分词
*/
public void analyze(AnalyzeContext context) {
// 处理中文数词
this.processCNumber(context);
// 处理中文量词
this.processCount(context);
// 判断是否锁定缓冲区
if (this.nStart == -1 && this.nEnd == -1 && countHits.isEmpty()) {
// 对缓冲区解锁
context.unlockBuffer(SEGMENTER_NAME);
} else {
context.lockBuffer(SEGMENTER_NAME);
}
}
/**
* 重置子分词器状态
*/
public void reset() {
nStart = -1;
nEnd = -1;
countHits.clear();
}
/**
* 处理数词
*/
private void processCNumber(AnalyzeContext context) {
if (nStart == -1 && nEnd == -1) {// 初始状态
if (CharacterUtil.CHAR_CHINESE == context.getCurrentCharType()
&& CHN_NUMBER_CHARS.contains(context.getCurrentChar())) {
// 记录数词的起始、结束位置
nStart = context.getCursor();
nEnd = context.getCursor();
}
} else {// 正在处理状态
if (CharacterUtil.CHAR_CHINESE == context.getCurrentCharType()
&& CHN_NUMBER_CHARS.contains(context.getCurrentChar())) {
// 记录数词的结束位置
nEnd = context.getCursor();
} else {
// 输出数词
this.outputNumLexeme(context);
// 重置头尾指针
nStart = -1;
nEnd = -1;
}
}
// 缓冲区已经用完,还有尚未输出的数词
if (context.isBufferConsumed()) {
if (nStart != -1 && nEnd != -1) {
// 输出数词
outputNumLexeme(context);
// 重置头尾指针
nStart = -1;
nEnd = -1;
}
}
}
/**
* 处理中文量词
*
* @param context 需要处理的内容
*/
private void processCount(AnalyzeContext context) {
// 判断是否需要启动量词扫描
if (!this.needCountScan(context)) {
return;
}
if (CharacterUtil.CHAR_CHINESE == context.getCurrentCharType()) {
// 优先处理countHits中的hit
if (!this.countHits.isEmpty()) {
// 处理词段队列
Hit[] tmpArray = this.countHits.toArray(new Hit[0]);
for (Hit hit : tmpArray) {
hit = Dictionary.getSingleton().matchWithHit(context.getSegmentBuff(), context.getCursor(), hit);
if (hit.isMatch()) {
// 输出当前的词
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), hit.getBegin(), context.getCursor() - hit.getBegin() + 1, Lexeme.TYPE_COUNT);
context.addLexeme(newLexeme);
if (!hit.isPrefix()) {// 不是词前缀,hit不需要继续匹配,移除
this.countHits.remove(hit);
}
} else if (hit.isUnmatch()) {
// hit不是词,移除
this.countHits.remove(hit);
}
}
}
// *********************************
// 对当前指针位置的字符进行单字匹配
Hit singleCharHit = Dictionary.getSingleton().matchInQuantifierDict(context.getSegmentBuff(), context.getCursor(), 1);
// 首字为量词前缀
if (singleCharHit.isMatch()) {
// 输出当前的词
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), context.getCursor(), 1, Lexeme.TYPE_COUNT);
context.addLexeme(newLexeme);
}
// 前缀匹配则放入hit列表
if (singleCharHit.isPrefix()) {
// 前缀匹配则放入hit列表
this.countHits.add(singleCharHit);
}
} else {
// 输入的不是中文字符
// 清空未成形的量词
this.countHits.clear();
}
// 缓冲区数据已经读完,还有尚未输出的量词
if (context.isBufferConsumed()) {
// 清空未成形的量词
this.countHits.clear();
}
}
/**
* 判断是否需要扫描量词
*/
private boolean needCountScan(AnalyzeContext context) {
if ((nStart != -1 && nEnd != -1) || !countHits.isEmpty()) {
// 正在处理中文数词,或者正在处理量词
return true;
} else {
// 找到一个相邻的数词
if (!context.getOrgLexemes().isEmpty()) {
Lexeme l = context.getOrgLexemes().peekLast();
if (Lexeme.TYPE_CNUM == l.getLexemeType() || Lexeme.TYPE_ARABIC == l.getLexemeType()) {
return l.getBegin() + l.getLength() == context.getCursor();
}
}
}
return false;
}
/**
* 添加数词词元到结果集
*
* @param context 需要添加的词元
*/
private void outputNumLexeme(AnalyzeContext context) {
if (nStart > -1 && nEnd > -1) {
// 输出数词
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), nStart, nEnd - nStart + 1, Lexeme.TYPE_CNUM);
context.addLexeme(newLexeme);
}
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/CharacterUtil.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
/**
* 字符集识别工具类
*/
class CharacterUtil {
static final int CHAR_USELESS = 0;
static final int CHAR_ARABIC = 0X00000001;
static final int CHAR_ENGLISH = 0X00000002;
static final int CHAR_CHINESE = 0X00000004;
static final int CHAR_OTHER_CJK = 0X00000008;
/**
* 识别字符类型
*
* @param input 需要识别的字符
* @return int CharacterUtil定义的字符类型常量
*/
static int identifyCharType(char input) {
if (input >= '0' && input <= '9') {
return CHAR_ARABIC;
} else if ((input >= 'a' && input <= 'z')
|| (input >= 'A' && input <= 'Z')) {
return CHAR_ENGLISH;
} else {
Character.UnicodeBlock ub = Character.UnicodeBlock.of(input);
if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
|| ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A) {
//目前已知的中文字符UTF-8集合
return CHAR_CHINESE;
} else if (ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS //全角数字字符和日韩字符
//韩文字符集
|| ub == Character.UnicodeBlock.HANGUL_SYLLABLES
|| ub == Character.UnicodeBlock.HANGUL_JAMO
|| ub == Character.UnicodeBlock.HANGUL_COMPATIBILITY_JAMO
//日文字符集
|| ub == Character.UnicodeBlock.HIRAGANA //平假名
|| ub == Character.UnicodeBlock.KATAKANA //片假名
|| ub == Character.UnicodeBlock.KATAKANA_PHONETIC_EXTENSIONS) {
return CHAR_OTHER_CJK;
}
}
//其他的不做处理的字符
return CHAR_USELESS;
}
/**
* 进行字符规格化(全角转半角,大写转小写处理)
*
* @param input 需要转换的字符
* @return char
*/
static char regularize(char input) {
if (input == 12288) {
input = (char) 32;
} else if (input > 65280 && input < 65375) {
input = (char) (input - 65248);
} else if (input >= 'A' && input <= 'Z') {
input += 32;
}
return input;
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/IKArbitrator.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
import java.util.Stack;
import java.util.TreeSet;
/**
* IK分词歧义裁决器
*/
class IKArbitrator {
IKArbitrator() {}
/**
* 分词歧义处理
*
* @param context 内容
* @param useSmart 是否细粒度分词
*/
void process(AnalyzeContext context, boolean useSmart) {
QuickSortSet orgLexemes = context.getOrgLexemes();
Lexeme orgLexeme = orgLexemes.pollFirst();
LexemePath crossPath = new LexemePath();
while (orgLexeme != null) {
if (!crossPath.addCrossLexeme(orgLexeme)) {
// 找到与crossPath不相交的下一个crossPath
if (crossPath.size() == 1 || !useSmart) {
// crossPath没有歧义 或者 不做歧义处理
// 直接输出当前crossPath
context.addLexemePath(crossPath);
} else {
// 对当前的crossPath进行歧义处理
QuickSortSet.Cell headCell = crossPath.getHead();
LexemePath judgeResult = this.judge(headCell);
// 输出歧义处理结果judgeResult
context.addLexemePath(judgeResult);
}
// 把orgLexeme加入新的crossPath中
crossPath = new LexemePath();
crossPath.addCrossLexeme(orgLexeme);
}
orgLexeme = orgLexemes.pollFirst();
}
// 处理最后的path
if (crossPath.size() == 1 || !useSmart) {
// crossPath没有歧义 或者 不做歧义处理
// 直接输出当前crossPath
context.addLexemePath(crossPath);
} else {
// 对当前的crossPath进行歧义处理
QuickSortSet.Cell headCell = crossPath.getHead();
LexemePath judgeResult = this.judge(headCell);
// 输出歧义处理结果judgeResult
context.addLexemePath(judgeResult);
}
}
/**
* 歧义识别
*
* @param lexemeCell 歧义路径链表头
*/
private LexemePath judge(QuickSortSet.Cell lexemeCell) {
// 候选路径集合
TreeSet<LexemePath> pathOptions = new TreeSet<>();
// 候选结果路径
LexemePath option = new LexemePath();
// 对crossPath进行一次遍历,同时返回本次遍历中有冲突的Lexeme栈
Stack<QuickSortSet.Cell> lexemeStack = this.forwardPath(lexemeCell, option);
// 当前词元链并非最理想的,加入候选路径集合
pathOptions.add(option.copy());
// 存在歧义词,处理
QuickSortSet.Cell c;
while (!lexemeStack.isEmpty()) {
c = lexemeStack.pop();
// 回滚词元链
this.backPath(c.getLexeme(), option);
// 从歧义词位置开始,递归,生成可选方案
this.forwardPath(c, option);
pathOptions.add(option.copy());
}
// 返回集合中的最优方案
return pathOptions.first();
}
/**
* 向前遍历,添加词元,构造一个无歧义词元组合
*/
private Stack<QuickSortSet.Cell> forwardPath(QuickSortSet.Cell lexemeCell, LexemePath option) {
// 发生冲突的Lexeme栈
Stack<QuickSortSet.Cell> conflictStack = new Stack<>();
QuickSortSet.Cell c = lexemeCell;
// 迭代遍历Lexeme链表
while (c != null && c.getLexeme() != null) {
if (!option.addNotCrossLexeme(c.getLexeme())) {
// 词元交叉,添加失败则加入lexemeStack栈
conflictStack.push(c);
}
c = c.getNext();
}
return conflictStack;
}
/**
* 回滚词元链,直到它能够接受指定的词元
*/
private void backPath(Lexeme l, LexemePath option) {
while (option.checkCross(l)) {
option.removeTail();
}
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/IKSegmenter.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.3.1 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.cfg.DefaultConfig;
import org.wltea.analyzer.dic.Dictionary;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.List;
/**
* IK分词器主类
*/
public final class IKSegmenter {
/**
* 字符窜reader
*/
private Reader input;
/**
* 分词器配置项
*/
private final Configuration cfg;
/**
* 分词器上下文
*/
private AnalyzeContext context;
/**
* 分词处理器列表
*/
private List<ISegmenter> segmenters;
/**
* 分词歧义裁决器
*/
private IKArbitrator arbitrator;
/**
* IK分词器构造函数
*
* @param input 读取流
* @param useSmart 为true,使用智能分词策略
* 非智能分词:细粒度输出所有可能的切分结果
* 智能分词: 合并数词和量词,对分词结果进行歧义判断
*/
public IKSegmenter(Reader input, boolean useSmart) {
this.input = input;
this.cfg = DefaultConfig.getInstance();
this.cfg.setUseSmart(useSmart);
this.init();
}
/**
* IK分词器构造函数
*
* @param input 读取流
* @param cfg 使用自定义的Configuration构造分词器
*/
@SuppressWarnings("unused")
public IKSegmenter(Reader input, Configuration cfg) {
this.input = input;
this.cfg = cfg;
this.init();
}
/**
* 初始化
*/
private void init() {
// 初始化词典单例
Dictionary.initial(this.cfg);
// 初始化分词上下文
this.context = new AnalyzeContext(this.cfg);
// 加载子分词器
this.segmenters = this.loadSegmenters();
// 加载歧义裁决器
this.arbitrator = new IKArbitrator();
}
/**
* 初始化词典,加载子分词器实现
*
* @return List<ISegmenter>
*/
private List<ISegmenter> loadSegmenters() {
List<ISegmenter> segmenters = new ArrayList<>(4);
// 处理字母的子分词器
segmenters.add(new LetterSegmenter());
// 处理中文数量词的子分词器
segmenters.add(new CN_QuantifierSegmenter());
// 处理中文词的子分词器
segmenters.add(new CJKSegmenter());
return segmenters;
}
/**
* 分词,获取下一个词元
*
* @return Lexeme 词元对象
*/
public synchronized Lexeme next() throws IOException {
Lexeme l;
while ((l = context.getNextLexeme()) == null) {
/*
* 从reader中读取数据,填充buffer
* 如果reader是分次读入buffer的,那么buffer要 进行移位处理
* 移位处理上次读入的但未处理的数据
*/
int available = context.fillBuffer(this.input);
if (available <= 0) {
// reader已经读完
context.reset();
return null;
} else {
// 初始化指针
context.initCursor();
do {
// 遍历子分词器
for (ISegmenter segmenter : segmenters) {
segmenter.analyze(context);
}
// 字符缓冲区接近读完,需要读入新的字符
if (context.needRefillBuffer()) {
break;
}
// 向前移动指针
} while (context.moveCursor());
// 重置子分词器,为下轮循环进行初始化
for (ISegmenter segmenter : segmenters) {
segmenter.reset();
}
}
// 对分词进行歧义处理
this.arbitrator.process(context, this.cfg.useSmart());
// 将分词结果输出到结果集,并处理未切分的单个CJK字符
context.outputToResult();
// 记录本次分词的缓冲区位移
context.markBufferOffset();
}
return l;
}
/**
* 重置分词器到初始状态
*
* @param input 读取流
*/
public synchronized void reset(Reader input) {
this.input = input;
context.reset();
for (ISegmenter segmenter : segmenters) {
segmenter.reset();
}
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/ISegmenter.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
/**
* 子分词器接口
*/
interface ISegmenter {
/**
* 从分析器读取下一个可能分解的词元对象
*
* @param context 分词算法上下文
*/
void analyze(AnalyzeContext context);
/**
* 重置子分析器状态
*/
void reset();
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/LetterSegmenter.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
import java.util.Arrays;
/**
* 英文字符及阿拉伯数字子分词器
*/
class LetterSegmenter implements ISegmenter {
/**
* 子分词器标签
*/
private static final String SEGMENTER_NAME = "LETTER_SEGMENTER";
/**
* 链接符号
*/
private static final char[] Letter_Connector = new char[]{'#', '&', '+', '-', '.', '@', '_'};
/**
* 数字符号
*/
private static final char[] Num_Connector = new char[]{',', '.'};
/*
* 词元的开始位置,
* 同时作为子分词器状态标识
* 当start > -1 时,标识当前的分词器正在处理字符
*/
private int start;
/*
* 记录词元结束位置
* end记录的是在词元中最后一个出现的Letter但非Sign_Connector的字符的位置
*/
private int end;
/*
* 字母起始位置
*/
private int englishStart;
/*
* 字母结束位置
*/
private int englishEnd;
/*
* 阿拉伯数字起始位置
*/
private int arabicStart;
/*
* 阿拉伯数字结束位置
*/
private int arabicEnd;
LetterSegmenter() {
Arrays.sort(Letter_Connector);
Arrays.sort(Num_Connector);
this.start = -1;
this.end = -1;
this.englishStart = -1;
this.englishEnd = -1;
this.arabicStart = -1;
this.arabicEnd = -1;
}
/* (non-Javadoc)
* @see org.wltea.analyzer.core.ISegmenter#analyze(org.wltea.analyzer.core.AnalyzeContext)
*/
public void analyze(AnalyzeContext context) {
boolean bufferLockFlag;
// 处理英文字母
bufferLockFlag = this.processEnglishLetter(context);
// 处理阿拉伯字母
bufferLockFlag = this.processArabicLetter(context) || bufferLockFlag;
// 处理混合字母(这个要放最后处理,可以通过QuickSortSet排除重复)
bufferLockFlag = this.processMixLetter(context) || bufferLockFlag;
// 判断是否锁定缓冲区
if (bufferLockFlag) {
context.lockBuffer(SEGMENTER_NAME);
} else {
// 对缓冲区解锁
context.unlockBuffer(SEGMENTER_NAME);
}
}
/* (non-Javadoc)
* @see org.wltea.analyzer.core.ISegmenter#reset()
*/
public void reset() {
this.start = -1;
this.end = -1;
this.englishStart = -1;
this.englishEnd = -1;
this.arabicStart = -1;
this.arabicEnd = -1;
}
/**
* 处理数字字母混合输出
* 如:windos2000 | linliangyi2005@gmail.com
*
* @param context 内容
*/
private boolean processMixLetter(AnalyzeContext context) {
boolean needLock;
if (this.start == -1) {// 当前的分词器尚未开始处理字符
if (CharacterUtil.CHAR_ARABIC == context.getCurrentCharType()
|| CharacterUtil.CHAR_ENGLISH == context.getCurrentCharType()) {
// 记录起始指针的位置,标明分词器进入处理状态
this.start = context.getCursor();
this.end = start;
}
} else {// 当前的分词器正在处理字符
if (CharacterUtil.CHAR_ARABIC == context.getCurrentCharType()
|| CharacterUtil.CHAR_ENGLISH == context.getCurrentCharType()) {
// 记录下可能的结束位置
this.end = context.getCursor();
} else if (CharacterUtil.CHAR_USELESS == context.getCurrentCharType()
&& this.isLetterConnector(context.getCurrentChar())) {
// 记录下可能的结束位置
this.end = context.getCursor();
} else {
// 遇到非Letter字符,输出词元
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), this.start, this.end - this.start + 1, Lexeme.TYPE_LETTER);
context.addLexeme(newLexeme);
this.start = -1;
this.end = -1;
}
}
// 判断缓冲区是否已经读完
if (context.isBufferConsumed()) {
if (this.start != -1 && this.end != -1) {
// 缓冲以读完,输出词元
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), this.start, this.end - this.start + 1, Lexeme.TYPE_LETTER);
context.addLexeme(newLexeme);
this.start = -1;
this.end = -1;
}
}
// 判断是否锁定缓冲区
needLock = this.start != -1 || this.end != -1;
return needLock;
}
/**
* 处理纯英文字母输出
*
* @param context 内容
*/
private boolean processEnglishLetter(AnalyzeContext context) {
boolean needLock;
if (this.englishStart == -1) {// 当前的分词器尚未开始处理英文字符
if (CharacterUtil.CHAR_ENGLISH == context.getCurrentCharType()) {
// 记录起始指针的位置,标明分词器进入处理状态
this.englishStart = context.getCursor();
this.englishEnd = this.englishStart;
}
} else {// 当前的分词器正在处理英文字符
if (CharacterUtil.CHAR_ENGLISH == context.getCurrentCharType()) {
// 记录当前指针位置为结束位置
this.englishEnd = context.getCursor();
} else {
// 遇到非English字符,输出词元
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), this.englishStart, this.englishEnd - this.englishStart + 1, Lexeme.TYPE_ENGLISH);
context.addLexeme(newLexeme);
this.englishStart = -1;
this.englishEnd = -1;
}
}
// 判断缓冲区是否已经读完
if (context.isBufferConsumed()) {
if (this.englishStart != -1 && this.englishEnd != -1) {
// 缓冲以读完,输出词元
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), this.englishStart, this.englishEnd - this.englishStart + 1, Lexeme.TYPE_ENGLISH);
context.addLexeme(newLexeme);
this.englishStart = -1;
this.englishEnd = -1;
}
}
// 判断是否锁定缓冲区
needLock = this.englishStart != -1 || this.englishEnd != -1;
return needLock;
}
/**
* 处理阿拉伯数字输出
*
* @param context 内容
*/
private boolean processArabicLetter(AnalyzeContext context) {
boolean needLock;
if (this.arabicStart == -1) {// 当前的分词器尚未开始处理数字字符
if (CharacterUtil.CHAR_ARABIC == context.getCurrentCharType()) {
// 记录起始指针的位置,标明分词器进入处理状态
this.arabicStart = context.getCursor();
this.arabicEnd = this.arabicStart;
}
} else {// 当前的分词器正在处理数字字符
if (CharacterUtil.CHAR_ARABIC == context.getCurrentCharType()) {
// 记录当前指针位置为结束位置
this.arabicEnd = context.getCursor();
}/* else if (CharacterUtil.CHAR_USELESS == context.getCurrentCharType()
&& this.isNumConnector(context.getCurrentChar())) {
// 不输出数字,但不标记结束
}*/ else {
// //遇到非Arabic字符,输出词元
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), this.arabicStart, this.arabicEnd - this.arabicStart + 1, Lexeme.TYPE_ARABIC);
context.addLexeme(newLexeme);
this.arabicStart = -1;
this.arabicEnd = -1;
}
}
// 判断缓冲区是否已经读完
if (context.isBufferConsumed()) {
if (this.arabicStart != -1 && this.arabicEnd != -1) {
// 生成已切分的词元
Lexeme newLexeme = new Lexeme(context.getBufferOffset(), this.arabicStart, this.arabicEnd - this.arabicStart + 1, Lexeme.TYPE_ARABIC);
context.addLexeme(newLexeme);
this.arabicStart = -1;
this.arabicEnd = -1;
}
}
// 判断是否锁定缓冲区
needLock = this.arabicStart != -1 || this.arabicEnd != -1;
return needLock;
}
/**
* 判断是否是字母连接符号
*
* @param input 内容
*/
private boolean isLetterConnector(char input) {
int index = Arrays.binarySearch(Letter_Connector, input);
return index >= 0;
}
/**
* 判断是否是数字连接符号
*
* @param input 内容
*/
@SuppressWarnings("unused")
private boolean isNumConnector(char input) {
int index = Arrays.binarySearch(Num_Connector, input);
return index >= 0;
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/Lexeme.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
/**
* IK词元对象
*/
@SuppressWarnings("unused")
public class Lexeme implements Comparable<Lexeme> {
/**
* 英文
*/
static final int TYPE_ENGLISH = 1;
/**
* 数字
*/
static final int TYPE_ARABIC = 2;
/**
* 英文数字混合
*/
static final int TYPE_LETTER = 3;
/**
* 中文词元
*/
static final int TYPE_CNWORD = 4;
/**
* 中文单字
*/
static final int TYPE_CNCHAR = 64;
/**
* 日韩文字
*/
static final int TYPE_OTHER_CJK = 8;
/**
* 中文数词
*/
static final int TYPE_CNUM = 16;
/**
* 中文量词
*/
static final int TYPE_COUNT = 32;
/**
* 中文数量词
*/
static final int TYPE_CQUAN = 48;
/**
* 词元的起始位移
*/
private int offset;
/**
* 词元的相对起始位置
*/
private int begin;
/**
* 词元的长度
*/
private int length;
/**
* 词元文本
*/
private String lexemeText;
/**
* 词元类型
*/
private int lexemeType;
public Lexeme(int offset, int begin, int length, int lexemeType) {
this.offset = offset;
this.begin = begin;
if (length < 0) {
throw new IllegalArgumentException("length < 0");
}
this.length = length;
this.lexemeType = lexemeType;
}
/*
* 判断词元相等算法
* 起始位置偏移、起始位置、终止位置相同
* @see java.lang.Object#equals(Object o)
*/
public boolean equals(Object o) {
if (o == null) {
return false;
}
if (this == o) {
return true;
}
if (o instanceof Lexeme) {
Lexeme other = (Lexeme) o;
return this.offset == other.getOffset()
&& this.begin == other.getBegin()
&& this.length == other.getLength();
} else {
return false;
}
}
/*
* 词元哈希编码算法
* @see java.lang.Object#hashCode()
*/
public int hashCode() {
int absBegin = getBeginPosition();
int absEnd = getEndPosition();
return (absBegin * 37) + (absEnd * 31) + ((absBegin * absEnd) % getLength()) * 11;
}
/*
* 词元在排序集合中的比较算法
* @see java.lang.Comparable#compareTo(java.lang.Object)
*/
public int compareTo(Lexeme other) {
// 起始位置优先
if (this.begin < other.getBegin()) {
return -1;
} else if (this.begin == other.getBegin()) {
// 词元长度优先
// this.length < other.getLength()
return Integer.compare(other.getLength(), this.length);
} else {
return 1;
}
}
private int getOffset() {
return offset;
}
public void setOffset(int offset) {
this.offset = offset;
}
int getBegin() {
return begin;
}
/**
* 获取词元在文本中的起始位置
*
* @return int
*/
public int getBeginPosition() {
return offset + begin;
}
public void setBegin(int begin) {
this.begin = begin;
}
/**
* 获取词元在文本中的结束位置
*
* @return int
*/
public int getEndPosition() {
return offset + begin + length;
}
/**
* 获取词元的字符长度
*
* @return int
*/
public int getLength() {
return this.length;
}
public void setLength(int length) {
if (this.length < 0) {
throw new IllegalArgumentException("length < 0");
}
this.length = length;
}
/**
* 获取词元的文本内容
*
* @return String
*/
public String getLexemeText() {
if (lexemeText == null) {
return "";
}
return lexemeText;
}
void setLexemeText(String lexemeText) {
if (lexemeText == null) {
this.lexemeText = "";
this.length = 0;
} else {
this.lexemeText = lexemeText;
this.length = lexemeText.length();
}
}
/**
* 获取词元类型
*
* @return int
*/
int getLexemeType() {
return lexemeType;
}
/**
* 获取词元类型标示字符串
*
* @return String
*/
public String getLexemeTypeString() {
switch (lexemeType) {
case TYPE_ENGLISH:
return "ENGLISH";
case TYPE_ARABIC:
return "ARABIC";
case TYPE_LETTER:
return "LETTER";
case TYPE_CNWORD:
return "CN_WORD";
case TYPE_CNCHAR:
return "CN_CHAR";
case TYPE_OTHER_CJK:
return "OTHER_CJK";
case TYPE_COUNT:
return "COUNT";
case TYPE_CNUM:
return "TYPE_CNUM";
case TYPE_CQUAN:
return "TYPE_CQUAN";
default:
return "UNKNOWN";
}
}
public void setLexemeType(int lexemeType) {
this.lexemeType = lexemeType;
}
/**
* 合并两个相邻的词元
*
* @return boolean 词元是否成功合并
*/
boolean append(Lexeme l, int lexemeType) {
if (l != null && this.getEndPosition() == l.getBeginPosition()) {
this.length += l.getLength();
this.lexemeType = lexemeType;
return true;
} else {
return false;
}
}
/**
* ToString 方法
*
* @return 字符串输出
*/
public String toString() {
return this.getBeginPosition() + "-" + this.getEndPosition() +
" : " + this.lexemeText + " : \t" +
this.getLexemeTypeString();
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/LexemePath.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
/**
* Lexeme链(路径)
*/
@SuppressWarnings("unused")
class LexemePath extends QuickSortSet implements Comparable<LexemePath> {
/**
* 起始位置
*/
private int pathBegin;
/**
* 结束
*/
private int pathEnd;
/**
* 词元链的有效字符长度
*/
private int payloadLength;
LexemePath() {
this.pathBegin = -1;
this.pathEnd = -1;
this.payloadLength = 0;
}
/**
* 向LexemePath追加相交的Lexeme
*/
boolean addCrossLexeme(Lexeme lexeme) {
if (this.isEmpty()) {
this.addLexeme(lexeme);
this.pathBegin = lexeme.getBegin();
this.pathEnd = lexeme.getBegin() + lexeme.getLength();
this.payloadLength += lexeme.getLength();
return true;
} else if (this.checkCross(lexeme)) {
this.addLexeme(lexeme);
if (lexeme.getBegin() + lexeme.getLength() > this.pathEnd) {
this.pathEnd = lexeme.getBegin() + lexeme.getLength();
}
this.payloadLength = this.pathEnd - this.pathBegin;
return true;
} else {
return false;
}
}
/**
* 向LexemePath追加不相交的Lexeme
*/
boolean addNotCrossLexeme(Lexeme lexeme) {
if (this.isEmpty()) {
this.addLexeme(lexeme);
this.pathBegin = lexeme.getBegin();
this.pathEnd = lexeme.getBegin() + lexeme.getLength();
this.payloadLength += lexeme.getLength();
return true;
} else if (this.checkCross(lexeme)) {
return false;
} else {
this.addLexeme(lexeme);
this.payloadLength += lexeme.getLength();
Lexeme head = this.peekFirst();
this.pathBegin = head.getBegin();
Lexeme tail = this.peekLast();
this.pathEnd = tail.getBegin() + tail.getLength();
return true;
}
}
/**
* 移除尾部的Lexeme
*/
void removeTail() {
Lexeme tail = this.pollLast();
if (this.isEmpty()) {
this.pathBegin = -1;
this.pathEnd = -1;
this.payloadLength = 0;
} else {
this.payloadLength -= tail.getLength();
Lexeme newTail = this.peekLast();
this.pathEnd = newTail.getBegin() + newTail.getLength();
}
}
/**
* 检测词元位置交叉(有歧义的切分)
*/
boolean checkCross(Lexeme lexeme) {
return (lexeme.getBegin() >= this.pathBegin && lexeme.getBegin() < this.pathEnd)
|| (this.pathBegin >= lexeme.getBegin() && this.pathBegin < lexeme.getBegin() + lexeme.getLength());
}
int getPathBegin() {
return pathBegin;
}
int getPathEnd() {
return pathEnd;
}
/**
* 获取Path的有效词长
*/
int getPayloadLength() {
return this.payloadLength;
}
/**
* 获取LexemePath的路径长度
*/
private int getPathLength() {
return this.pathEnd - this.pathBegin;
}
/**
* X权重(词元长度积)
*/
private int getXWeight() {
int product = 1;
Cell c = this.getHead();
while (c != null && c.getLexeme() != null) {
product *= c.getLexeme().getLength();
c = c.getNext();
}
return product;
}
/**
* 词元位置权重
*/
private int getPWeight() {
int pWeight = 0;
int p = 0;
Cell c = this.getHead();
while (c != null && c.getLexeme() != null) {
p++;
pWeight += p * c.getLexeme().getLength();
c = c.getNext();
}
return pWeight;
}
LexemePath copy() {
LexemePath theCopy = new LexemePath();
theCopy.pathBegin = this.pathBegin;
theCopy.pathEnd = this.pathEnd;
theCopy.payloadLength = this.payloadLength;
Cell c = this.getHead();
while (c != null && c.getLexeme() != null) {
theCopy.addLexeme(c.getLexeme());
c = c.getNext();
}
return theCopy;
}
public int compareTo(LexemePath o) {
// 比较有效文本长度
if (this.payloadLength > o.payloadLength) {
return -1;
} else if (this.payloadLength < o.payloadLength) {
return 1;
}
// 比较词元个数,越少越好
if (this.size() < o.size()) {
return -1;
} else if (this.size() > o.size()) {
return 1;
}
// 路径跨度越大越好
if (this.getPathLength() > o.getPathLength()) {
return -1;
} else if (this.getPathLength() < o.getPathLength()) {
return 1;
}
// 根据统计学结论,逆向切分概率高于正向切分,因此位置越靠后的优先
if (this.pathEnd > o.pathEnd) {
return -1;
} else if (pathEnd < o.pathEnd) {
return 1;
}
// 词长越平均越好
if (this.getXWeight() > o.getXWeight()) {
return -1;
} else if (this.getXWeight() < o.getXWeight()) {
return 1;
}
// 词元位置权重比较
if (this.getPWeight() > o.getPWeight()) {
return -1;
} else if (this.getPWeight() < o.getPWeight()) {
return 1;
}
return 0;
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("pathBegin : ").append(pathBegin).append("\r\n");
sb.append("pathEnd : ").append(pathEnd).append("\r\n");
sb.append("payloadLength : ").append(payloadLength).append("\r\n");
Cell head = this.getHead();
while (head != null) {
sb.append("lexeme : ").append(head.getLexeme()).append("\r\n");
head = head.getNext();
}
return sb.toString();
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/core/QuickSortSet.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.2.0版本 由 Magese (magese@live.cn) 更新
* release 8.2.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.core;
/**
* IK分词器专用的Lexeme快速排序集合
*/
class QuickSortSet {
/**
* 链表头
*/
private Cell head;
/**
* 链表尾
*/
private Cell tail;
/**
* 链表的实际大小
*/
private int size;
QuickSortSet() {
this.size = 0;
}
/**
* 向链表集合添加词元
*/
void addLexeme(Lexeme lexeme) {
Cell newCell = new Cell(lexeme);
if (this.size == 0) {
this.head = newCell;
this.tail = newCell;
this.size++;
} else {
if (this.tail.compareTo(newCell) < 0) {
// 词元接入链表尾部
this.tail.next = newCell;
newCell.prev = this.tail;
this.tail = newCell;
this.size++;
} else if (this.head.compareTo(newCell) > 0) {
// 词元接入链表头部
this.head.prev = newCell;
newCell.next = this.head;
this.head = newCell;
this.size++;
} else {
// 从尾部上逆
Cell index = this.tail;
while (index != null && index.compareTo(newCell) > 0) {
index = index.prev;
}
// 词元插入链表中的某个位置
if ((index != null ? index.compareTo(newCell) : 1) < 0) {
newCell.prev = index;
newCell.next = index.next;
index.next.prev = newCell;
index.next = newCell;
this.size++;
}
}
}
}
/**
* 返回链表头部元素
*/
Lexeme peekFirst() {
if (this.head != null) {
return this.head.lexeme;
}
return null;
}
/**
* 取出链表集合的第一个元素
*
* @return Lexeme
*/
Lexeme pollFirst() {
if (this.size == 1) {
Lexeme first = this.head.lexeme;
this.head = null;
this.tail = null;
this.size--;
return first;
} else if (this.size > 1) {
Lexeme first = this.head.lexeme;
this.head = this.head.next;
this.size--;
return first;
} else {
return null;
}
}
/**
* 返回链表尾部元素
*/
Lexeme peekLast() {
if (this.tail != null) {
return this.tail.lexeme;
}
return null;
}
/**
* 取出链表集合的最后一个元素
*
* @return Lexeme
*/
Lexeme pollLast() {
if (this.size == 1) {
Lexeme last = this.head.lexeme;
this.head = null;
this.tail = null;
this.size--;
return last;
} else if (this.size > 1) {
Lexeme last = this.tail.lexeme;
this.tail = this.tail.prev;
this.size--;
return last;
} else {
return null;
}
}
/**
* 返回集合大小
*/
int size() {
return this.size;
}
/**
* 判断集合是否为空
*/
boolean isEmpty() {
return this.size == 0;
}
/**
* 返回lexeme链的头部
*/
Cell getHead() {
return this.head;
}
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
* update by Magese(magese@live.cn)
*/
@SuppressWarnings("unused")
static class Cell implements Comparable<Cell> {
private Cell prev;
private Cell next;
private final Lexeme lexeme;
Cell(Lexeme lexeme) {
if (lexeme == null) {
throw new IllegalArgumentException("lexeme must not be null");
}
this.lexeme = lexeme;
}
public int compareTo(Cell o) {
return this.lexeme.compareTo(o.lexeme);
}
public Cell getPrev() {
return this.prev;
}
Cell getNext() {
return this.next;
}
public Lexeme getLexeme() {
return this.lexeme;
}
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/dic/DictSegment.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.dic;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
/**
* 词典树分段,表示词典树的一个分枝
*/
@SuppressWarnings("unused")
class DictSegment implements Comparable<DictSegment> {
/**
* 公用字典表,存储汉字
*/
private static final Map<Character, Character> charMap = new HashMap<>(16, 0.95f);
/**
* 数组大小上限
*/
private static final int ARRAY_LENGTH_LIMIT = 3;
/**
* Map存储结构
*/
private volatile Map<Character, DictSegment> childrenMap;
/**
* 数组方式存储结构
*/
private volatile DictSegment[] childrenArray;
/**
* 当前节点上存储的字符
*/
private final Character nodeChar;
/**
* 当前节点存储的Segment数目
* storeSize <=ARRAY_LENGTH_LIMIT ,使用数组存储, storeSize >ARRAY_LENGTH_LIMIT ,则使用Map存储
*/
private int storeSize = 0;
/**
* 当前DictSegment状态 ,默认 0 , 1表示从根节点到当前节点的路径表示一个词
*/
private int nodeState = 0;
DictSegment(Character nodeChar) {
if (nodeChar == null) {
throw new IllegalArgumentException("参数为空异常,字符不能为空");
}
this.nodeChar = nodeChar;
}
Character getNodeChar() {
return nodeChar;
}
/*
* 判断是否有下一个节点
*/
private boolean hasNextNode() {
return this.storeSize > 0;
}
/**
* 匹配词段
*
* @return Hit
*/
Hit match(char[] charArray) {
return this.match(charArray, 0, charArray.length, null);
}
/**
* 匹配词段
*
* @return Hit
*/
Hit match(char[] charArray, int begin, int length) {
return this.match(charArray, begin, length, null);
}
/**
* 匹配词段
*
* @return Hit
*/
Hit match(char[] charArray, int begin, int length, Hit searchHit) {
if (searchHit == null) {
// 如果hit为空,新建
searchHit = new Hit();
// 设置hit的其实文本位置
searchHit.setBegin(begin);
} else {
// 否则要将HIT状态重置
searchHit.setUnmatch();
}
// 设置hit的当前处理位置
searchHit.setEnd(begin);
Character keyChar = charArray[begin];
DictSegment ds = null;
// 引用实例变量为本地变量,避免查询时遇到更新的同步问题
DictSegment[] segmentArray = this.childrenArray;
Map<Character, DictSegment> segmentMap = this.childrenMap;
// STEP1 在节点中查找keyChar对应的DictSegment
if (segmentArray != null) {
// 在数组中查找
DictSegment keySegment = new DictSegment(keyChar);
int position = Arrays.binarySearch(segmentArray, 0, this.storeSize, keySegment);
if (position >= 0) {
ds = segmentArray[position];
}
} else if (segmentMap != null) {
// 在map中查找
ds = segmentMap.get(keyChar);
}
// STEP2 找到DictSegment,判断词的匹配状态,是否继续递归,还是返回结果
if (ds != null) {
if (length > 1) {
// 词未匹配完,继续往下搜索
return ds.match(charArray, begin + 1, length - 1, searchHit);
} else if (length == 1) {
// 搜索最后一个char
if (ds.nodeState == 1) {
// 添加HIT状态为完全匹配
searchHit.setMatch();
}
if (ds.hasNextNode()) {
// 添加HIT状态为前缀匹配
searchHit.setPrefix();
// 记录当前位置的DictSegment
searchHit.setMatchedDictSegment(ds);
}
return searchHit;
}
}
// STEP3 没有找到DictSegment, 将HIT设置为不匹配
return searchHit;
}
/**
* 加载填充词典片段
*/
void fillSegment(char[] charArray) {
this.fillSegment(charArray, 0, charArray.length, 1);
}
/**
* 屏蔽词典中的一个词
*/
void disableSegment(char[] charArray) {
this.fillSegment(charArray, 0, charArray.length, 0);
}
/**
* 加载填充词典片段
*/
private synchronized void fillSegment(char[] charArray, int begin, int length, int enabled) {
// 获取字典表中的汉字对象
Character beginChar = charArray[begin];
Character keyChar = charMap.get(beginChar);
// 字典中没有该字,则将其添加入字典
if (keyChar == null) {
charMap.put(beginChar, beginChar);
keyChar = beginChar;
}
// 搜索当前节点的存储,查询对应keyChar的keyChar,如果没有则创建
DictSegment ds = lookforSegment(keyChar, enabled);
if (ds != null) {
// 处理keyChar对应的segment
if (length > 1) {
// 词元还没有完全加入词典树
ds.fillSegment(charArray, begin + 1, length - 1, enabled);
} else if (length == 1) {
// 已经是词元的最后一个char,设置当前节点状态为enabled,
// enabled=1表明一个完整的词,enabled=0表示从词典中屏蔽当前词
ds.nodeState = enabled;
}
}
}
/**
* 查找本节点下对应的keyChar的segment *
*
* @param create =1如果没有找到,则创建新的segment ; =0如果没有找到,不创建,返回null
*/
private DictSegment lookforSegment(Character keyChar, int create) {
DictSegment ds = null;
if (this.storeSize <= ARRAY_LENGTH_LIMIT) {
// 获取数组容器,如果数组未创建则创建数组
DictSegment[] segmentArray = getChildrenArray();
// 搜寻数组
DictSegment keySegment = new DictSegment(keyChar);
int position = Arrays.binarySearch(segmentArray, 0, this.storeSize, keySegment);
if (position >= 0) {
ds = segmentArray[position];
}
// 遍历数组后没有找到对应的segment
if (ds == null && create == 1) {
ds = keySegment;
if (this.storeSize < ARRAY_LENGTH_LIMIT) {
// 数组容量未满,使用数组存储
segmentArray[this.storeSize] = ds;
// segment数目+1
this.storeSize++;
Arrays.sort(segmentArray, 0, this.storeSize);
} else {
// 数组容量已满,切换Map存储
// 获取Map容器,如果Map未创建,则创建Map
Map<Character, DictSegment> segmentMap = getChildrenMap();
// 将数组中的segment迁移到Map中
migrate(segmentArray, segmentMap);
// 存储新的segment
segmentMap.put(keyChar, ds);
// segment数目+1 , 必须在释放数组前执行storeSize++ , 确保极端情况下,不会取到空的数组
this.storeSize++;
// 释放当前的数组引用
this.childrenArray = null;
}
}
} else {
// 获取Map容器,如果Map未创建,则创建Map
Map<Character, DictSegment> segmentMap = getChildrenMap();
// 搜索Map
ds = segmentMap.get(keyChar);
if (ds == null && create == 1) {
// 构造新的segment
ds = new DictSegment(keyChar);
segmentMap.put(keyChar, ds);
// 当前节点存储segment数目+1
this.storeSize++;
}
}
return ds;
}
/**
* 获取数组容器
* 线程同步方法
*/
private DictSegment[] getChildrenArray() {
if (this.childrenArray == null) {
synchronized (this) {
if (this.childrenArray == null) {
this.childrenArray = new DictSegment[ARRAY_LENGTH_LIMIT];
}
}
}
return this.childrenArray;
}
/**
* 获取Map容器
* 线程同步方法
*/
private Map<Character, DictSegment> getChildrenMap() {
if (this.childrenMap == null) {
synchronized (this) {
if (this.childrenMap == null) {
this.childrenMap = new HashMap<>(ARRAY_LENGTH_LIMIT * 2, 0.8f);
}
}
}
return this.childrenMap;
}
/**
* 将数组中的segment迁移到Map中
*/
private void migrate(DictSegment[] segmentArray, Map<Character, DictSegment> segmentMap) {
for (DictSegment segment : segmentArray) {
if (segment != null) {
segmentMap.put(segment.nodeChar, segment);
}
}
}
/**
* 实现Comparable接口
*
* @return int
*/
public int compareTo(DictSegment o) {
// 对当前节点存储的char进行比较
return this.nodeChar.compareTo(o.nodeChar);
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/dic/Dictionary.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.dic;
import org.wltea.analyzer.cfg.Configuration;
import org.wltea.analyzer.cfg.DefaultConfig;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;
/**
* 词典管理类,单例模式
*/
@SuppressWarnings("unused")
public class Dictionary {
/*
* 词典单子实例
*/
private static volatile Dictionary singleton;
/*
* 主词典对象
*/
private DictSegment _MainDict;
/*
* 停止词词典
*/
private DictSegment _StopWordDict;
/*
* 量词词典
*/
private DictSegment _QuantifierDict;
/**
* 配置对象
*/
private final Configuration cfg;
/**
* 私有构造方法,阻止外部直接实例化本类
*
* @param cfg ik分词器配置实例
*/
private Dictionary(Configuration cfg) {
this.cfg = cfg;
this.loadMainDict();
this.loadStopWordDict();
this.loadQuantifierDict();
}
/**
* 词典初始化
* 由于IK Analyzer的词典采用Dictionary类的静态方法进行词典初始化
* 只有当Dictionary类被实际调用时,才会开始载入词典,
* 这将延长首次分词操作的时间
* 该方法提供了一个在应用加载阶段就初始化字典的手段
*/
public static void initial(Configuration cfg) {
if (singleton == null) {
synchronized (Dictionary.class) {
if (singleton == null) {
singleton = new Dictionary(cfg);
}
}
}
}
/**
* 获取词典单子实例
*
* @return Dictionary 单例对象
*/
public static Dictionary getSingleton() {
if (singleton == null) {
throw new IllegalStateException("词典尚未初始化,请先调用initial方法");
}
return singleton;
}
/**
* 重新更新词典
* 由于停用词等不经常变也不建议常增加,故这里只修改动态扩展词库
*
* @param inputStreamReaderList 词典文件IO流集合
*/
public static void reloadDic(List<Reader> inputStreamReaderList) {
// 如果本类单例尚未实例化,则先进行初始化操作
if (singleton == null) {
Configuration cfg = DefaultConfig.getInstance();
initial(cfg);
}
// 对词典流集合进行循环读取,将读取到的词语加载到主词典中
for (Reader in : inputStreamReaderList) {
try {
LineNumberReader br = new LineNumberReader(in);
String theWord;
while ((theWord = br.readLine()) != null) {
if (theWord.trim().length() == 0 || theWord.trim().charAt(0) == '#') continue;
singleton._MainDict.fillSegment(theWord.trim().toLowerCase().toCharArray());
}
} catch (IOException ioe) {
System.err.println("Other Dictionary loading exception.");
ioe.printStackTrace();
} finally {
try {
if (in != null) {
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* 批量加载新词条
*
* @param words 词条列表
*/
public void addWords(Collection<String> words) {
if (words != null) {
for (String word : words) {
if (word != null) {
// 批量加载词条到主内存词典中
singleton._MainDict.fillSegment(word.trim().toLowerCase().toCharArray());
}
}
}
}
/**
* 批量移除(屏蔽)词条
*/
public void disableWords(Collection<String> words) {
if (words != null) {
for (String word : words) {
if (word != null) {
// 批量屏蔽词条
singleton._MainDict.disableSegment(word.trim().toLowerCase().toCharArray());
}
}
}
}
/**
* 检索匹配主词典
*
* @return Hit 匹配结果描述
*/
public Hit matchInMainDict(char[] charArray) {
return singleton._MainDict.match(charArray);
}
/**
* 检索匹配主词典
*
* @return Hit 匹配结果描述
*/
public Hit matchInMainDict(char[] charArray, int begin, int length) {
return singleton._MainDict.match(charArray, begin, length);
}
/**
* 检索匹配量词词典
*
* @return Hit 匹配结果描述
*/
public Hit matchInQuantifierDict(char[] charArray, int begin, int length) {
return singleton._QuantifierDict.match(charArray, begin, length);
}
/**
* 从已匹配的Hit中直接取出DictSegment,继续向下匹配
*
* @return Hit
*/
public Hit matchWithHit(char[] charArray, int currentIndex, Hit matchedHit) {
DictSegment ds = matchedHit.getMatchedDictSegment();
return ds.match(charArray, currentIndex, 1, matchedHit);
}
/**
* 判断是否是停止词
*
* @return boolean
*/
public boolean isStopWord(char[] charArray, int begin, int length) {
return singleton._StopWordDict.match(charArray, begin, length).isMatch();
}
/**
* 加载主词典及扩展词典
*/
private void loadMainDict() {
// 建立一个主词典实例
_MainDict = new DictSegment((char) 0);
// 获取是否加载主词典
if (cfg.useMainDict()) {
// 读取主词典文件
InputStream is = this.getClass().getClassLoader().getResourceAsStream(cfg.getMainDictionary());
if (is == null) {
throw new RuntimeException("Main Dictionary not found!!!");
}
try {
readDict(is, _MainDict);
} catch (IOException ioe) {
System.err.println("Main Dictionary loading exception.");
ioe.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// 加载扩展词典
this.loadExtDict();
}
/**
* 加载用户配置的扩展词典到主词库表
*/
private void loadExtDict() {
// 加载扩展词典配置
List<String> extDictFiles = cfg.getExtDictionarys();
if (extDictFiles != null) {
InputStream is;
for (String extDictName : extDictFiles) {
// 读取扩展词典文件
System.out.println("Load extended dictionary:" + extDictName);
is = this.getClass().getClassLoader().getResourceAsStream(extDictName);
// 如果找不到扩展的字典,则忽略
if (is == null) {
continue;
}
try {
readDict(is, _MainDict);
} catch (IOException ioe) {
System.err.println("Extension Dictionary loading exception.");
ioe.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 加载用户扩展的停止词词典
*/
private void loadStopWordDict() {
// 建立一个主词典实例
_StopWordDict = new DictSegment((char) 0);
// 加载扩展停止词典
List<String> extStopWordDictFiles = cfg.getExtStopWordDictionarys();
if (extStopWordDictFiles != null) {
InputStream is;
for (String extStopWordDictName : extStopWordDictFiles) {
System.out.println("Load stopwords dictionary:" + extStopWordDictName);
// 读取扩展词典文件
is = this.getClass().getClassLoader().getResourceAsStream(extStopWordDictName);
// 如果找不到扩展的字典,则忽略
if (is == null) {
continue;
}
try {
readDict(is, _StopWordDict);
} catch (IOException ioe) {
System.err.println("Extension Stop word Dictionary loading exception.");
ioe.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
/**
* 加载量词词典
*/
private void loadQuantifierDict() {
// 建立一个量词典实例
_QuantifierDict = new DictSegment((char) 0);
// 读取量词词典文件
InputStream is = this.getClass().getClassLoader().getResourceAsStream(cfg.getQuantifierDictionary());
if (is == null) {
throw new RuntimeException("Quantifier Dictionary not found!!!");
}
try {
readDict(is, _QuantifierDict);
} catch (IOException ioe) {
System.err.println("Quantifier Dictionary loading exception.");
ioe.printStackTrace();
} finally {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 读取词典文件到词典树中
*
* @param is 文件输入流
* @param dictSegment 词典树分段
* @throws IOException 读取异常
*/
private void readDict(InputStream is, DictSegment dictSegment) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8), 512);
String theWord;
do {
theWord = br.readLine();
if (theWord != null && !"".equals(theWord.trim())) {
dictSegment.fillSegment(theWord.trim().toLowerCase().toCharArray());
}
} while (theWord != null);
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/dic/Hit.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.dic;
/**
* 表示一次词典匹配的命中
*/
@SuppressWarnings("unused")
public class Hit {
/**
* Hit不匹配
*/
private static final int UNMATCH = 0x00000000;
/**
* Hit完全匹配
*/
private static final int MATCH = 0x00000001;
/**
* Hit前缀匹配
*/
private static final int PREFIX = 0x00000010;
/**
* 该HIT当前状态,默认未匹配
*/
private int hitState = UNMATCH;
/**
* 记录词典匹配过程中,当前匹配到的词典分支节点
*/
private DictSegment matchedDictSegment;
/**
* 词段开始位置
*/
private int begin;
/**
* 词段的结束位置
*/
private int end;
/**
* 判断是否完全匹配
*/
public boolean isMatch() {
return (this.hitState & MATCH) > 0;
}
/**
*
*/
void setMatch() {
this.hitState = this.hitState | MATCH;
}
/**
* 判断是否是词的前缀
*/
public boolean isPrefix() {
return (this.hitState & PREFIX) > 0;
}
/**
*
*/
void setPrefix() {
this.hitState = this.hitState | PREFIX;
}
/**
* 判断是否是不匹配
*/
public boolean isUnmatch() {
return this.hitState == UNMATCH ;
}
void setUnmatch() {
this.hitState = UNMATCH;
}
DictSegment getMatchedDictSegment() {
return matchedDictSegment;
}
void setMatchedDictSegment(DictSegment matchedDictSegment) {
this.matchedDictSegment = matchedDictSegment;
}
public int getBegin() {
return begin;
}
void setBegin(int begin) {
this.begin = begin;
}
public int getEnd() {
return end;
}
void setEnd(int end) {
this.end = end;
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/lucene/IKAnalyzer.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.lucene;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.Tokenizer;
/**
* IK分词器,Lucene Analyzer接口实现
*/
@SuppressWarnings("unused")
public final class IKAnalyzer extends Analyzer {
private final boolean useSmart;
private boolean useSmart() {
return useSmart;
}
/**
* IK分词器Lucene Analyzer接口实现类
* 默认细粒度切分算法
*/
public IKAnalyzer() {
this(false);
}
/**
* IK分词器Lucene Analyzer接口实现类
*
* @param useSmart 当为true时,分词器进行智能切分
*/
public IKAnalyzer(boolean useSmart) {
super();
this.useSmart = useSmart;
}
/**
* 重载Analyzer接口,构造分词组件
*/
@Override
protected TokenStreamComponents createComponents(String fieldName) {
Tokenizer _IKTokenizer = new IKTokenizer(this.useSmart());
return new TokenStreamComponents(_IKTokenizer);
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/lucene/IKTokenizer.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.lucene;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.tokenattributes.CharTermAttribute;
import org.apache.lucene.analysis.tokenattributes.OffsetAttribute;
import org.apache.lucene.analysis.tokenattributes.TypeAttribute;
import org.apache.lucene.util.AttributeFactory;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import java.io.IOException;
/**
* IK分词器 Lucene Tokenizer适配器类
*/
@SuppressWarnings({"unused", "FinalMethodInFinalClass"})
public final class IKTokenizer extends Tokenizer {
/**
* IK分词器实现
*/
private IKSegmenter _IKImplement;
/**
* 词元文本属性
*/
private CharTermAttribute termAtt;
/**
* 词元位移属性
*/
private OffsetAttribute offsetAtt;
/**
* 词元分类属性(该属性分类参考org.wltea.analyzer.core.Lexeme中的分类常量)
*/
private TypeAttribute typeAtt;
/**
* 记录最后一个词元的结束位置
*/
private int endPosition;
/**
* Lucene 7.6 Tokenizer适配器类构造函数
*/
public IKTokenizer() {
this(false);
}
IKTokenizer(boolean useSmart) {
super();
init(useSmart);
}
public IKTokenizer(AttributeFactory factory) {
this(factory, false);
}
IKTokenizer(AttributeFactory factory, boolean useSmart) {
super(factory);
init(useSmart);
}
private void init(boolean useSmart) {
offsetAtt = addAttribute(OffsetAttribute.class);
termAtt = addAttribute(CharTermAttribute.class);
typeAtt = addAttribute(TypeAttribute.class);
_IKImplement = new IKSegmenter(input, useSmart);
}
/*
* (non-Javadoc)
* @see org.apache.lucene.analysis.TokenStream#incrementToken()
*/
@Override
public boolean incrementToken() throws IOException {
// 清除所有的词元属性
clearAttributes();
Lexeme nextLexeme = _IKImplement.next();
if (nextLexeme != null) {
// 将Lexeme转成Attributes
// 设置词元文本
termAtt.append(nextLexeme.getLexemeText());
// 设置词元长度
termAtt.setLength(nextLexeme.getLength());
// 设置词元位移
offsetAtt.setOffset(nextLexeme.getBeginPosition(), nextLexeme.getEndPosition());
// 记录分词的最后位置
endPosition = nextLexeme.getEndPosition();
// 记录词元分类
typeAtt.setType(nextLexeme.getLexemeTypeString());
// 返会true告知还有下个词元
return true;
}
// 返会false告知词元输出完毕
return false;
}
/*
* (non-Javadoc)
* @see org.apache.lucene.analysis.Tokenizer#reset(java.io.Reader)
*/
@Override
public void reset() throws IOException {
super.reset();
_IKImplement.reset(input);
}
@Override
public final void end() {
// set final offset
int finalOffset = correctOffset(this.endPosition);
offsetAtt.setOffset(finalOffset, finalOffset);
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/lucene/IKTokenizerFactory.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.lucene;
import org.apache.lucene.analysis.Tokenizer;
import org.apache.lucene.analysis.util.ResourceLoader;
import org.apache.lucene.analysis.util.ResourceLoaderAware;
import org.apache.lucene.analysis.util.TokenizerFactory;
import org.apache.lucene.util.AttributeFactory;
import org.wltea.analyzer.dic.Dictionary;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CodingErrorAction;
import java.nio.charset.StandardCharsets;
import java.util.*;
/**
* 分词器工厂类
*
* @author <a href="magese@live.cn">Magese</a>
*/
public class IKTokenizerFactory extends TokenizerFactory implements ResourceLoaderAware, UpdateThread.UpdateJob {
private boolean useSmart;
private ResourceLoader loader;
private long lastUpdateTime = -1L;
private String conf = "ik.conf";
public IKTokenizerFactory(Map<String, String> args) {
super(args);
String useSmartArg = args.get("useSmart");
String confArg = args.get("conf");
this.setUseSmart(Boolean.parseBoolean(useSmartArg));
this.setConf(confArg);
}
@Override
public Tokenizer create(AttributeFactory factory) {
return new IKTokenizer(factory, useSmart());
}
/**
* 通知方法,用于获取工厂使用的资源文件路径等信息,实现与{@link ResourceLoaderAware#inform(ResourceLoader)}
* 当该方法被调用时,将当前实例注册到更新任务中
*
* @param resourceLoader 类路径资源加载实例
* @throws IOException IO读写异常
*/
@Override
public void inform(ResourceLoader resourceLoader) throws IOException {
System.out.printf("IKTokenizerFactory " + this.hashCode() + " inform conf: %s%n", getConf());
this.loader = resourceLoader;
update();
if ((getConf() != null) && (!getConf().trim().isEmpty())) {
UpdateThread.getInstance().register(this);
}
}
/**
* 实现更新任务接口的更新方法
*
* @throws IOException 读取文件异常
*/
@Override
public void update() throws IOException {
// 默认UTF-8解码
CharsetDecoder decoder = StandardCharsets.UTF_8.newDecoder()
.onMalformedInput(CodingErrorAction.REPORT)
.onUnmappableCharacter(CodingErrorAction.REPORT);
// 获取ik.conf配置文件信息
Properties p = canUpdate();
if (p != null) {
// 获取词典表名称集合
List<String> dicPaths = SplitFileNames(p.getProperty("files"));
// 获取词典文件的IO流
List<Reader> inputStreamReaderList = new ArrayList<>();
for (String path : dicPaths) {
if ((path != null) && (!path.isEmpty())) {
Reader isr = new InputStreamReader(loader.openResource(path), decoder);
inputStreamReaderList.add(isr);
}
}
// 如果IO流集合不为空则执行加载词典
if (!inputStreamReaderList.isEmpty())
Dictionary.reloadDic(inputStreamReaderList);
}
}
/**
* 检查是否要更新
*/
private Properties canUpdate() {
try {
if (getConf() == null)
return null;
Properties p = new Properties();
InputStream confStream = this.loader.openResource(getConf()); // 获取配置文件流
p.load(confStream); // 读取配置文件
confStream.close(); // 关闭文件流
String lastupdate = p.getProperty("lastupdate", "0"); // 获取最后更新数字
Long t = new Long(lastupdate);
if (t > this.lastUpdateTime) { // 如果最后更新的数字大于上次记录的最后更新数字
this.lastUpdateTime = t; // 将最后更新数字替换为当次的数字
String paths = p.getProperty("files"); // 获取词典文件名
if ((paths == null) || (paths.trim().isEmpty()))
return null;
System.out.println("loading " + getConf() + " files success.");
return p;
}
this.lastUpdateTime = t;
return null;
} catch (Exception e) {
System.err.println("parsing " + getConf() + " NullPointerException!!!" + Arrays.toString(e.getStackTrace()));
}
return null;
}
/**
* 对多个文件名进行切割
*
* @param fileNames 多个文件名
* @return 文件名集合
*/
private static List<String> SplitFileNames(String fileNames) {
if (fileNames == null) {
return Collections.emptyList();
}
List<String> result = new ArrayList<>();
Collections.addAll(result, fileNames.split("[,\\s]+"));
return result;
}
/* getter & setter */
private boolean useSmart() {
return useSmart;
}
private void setUseSmart(boolean useSmart) {
this.useSmart = useSmart;
}
private String getConf() {
return conf;
}
private void setConf(String conf) {
this.conf = conf;
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/lucene/UpdateThread.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.lucene;
import java.io.IOException;
import java.util.Vector;
/**
* 更新扩展词典子线程类
*/
public class UpdateThread implements Runnable {
private static final long INTERVAL = 30000L; // 循环等待时间
private final Vector<UpdateJob> filterFactorys; // 更新任务集合
/**
* 私有化构造器,阻止外部进行实例化
*/
private UpdateThread() {
this.filterFactorys = new Vector<>();
Thread worker = new Thread(this);
worker.setDaemon(true);
worker.start();
}
/**
* 静态内部类,实现线程安全单例模式
*/
private static class Builder {
private static final UpdateThread singleton = new UpdateThread();
}
/**
* 获取本类的实例
* 线程安全单例模式
*
* @return 本类的实例
*/
static UpdateThread getInstance() {
return UpdateThread.Builder.singleton;
}
/**
* 将运行中的IK分词工厂实例注册到本类定时任务中
*
* @param filterFactory 运行中的IK分词器
*/
void register(UpdateJob filterFactory) {
this.filterFactorys.add(filterFactory);
}
/**
* 子线程执行任务
*/
@Override
public void run() {
//noinspection InfiniteLoopStatement
while (true) {
try {
//noinspection BusyWait
Thread.sleep(INTERVAL);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 如果更新字典任务集合不为空
if (!this.filterFactorys.isEmpty()) {
// 进行循环并执行更新
for (UpdateJob factory : this.filterFactorys) {
try {
factory.update();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
public interface UpdateJob {
void update() throws IOException;
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/query/IKQueryExpressionParser.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.query;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.*;
import org.apache.lucene.search.BooleanClause.Occur;
import org.apache.lucene.util.BytesRef;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Stack;
/**
* IK简易查询表达式解析
* 结合SWMCQuery算法
*
* @author linliangyi
*/
public class IKQueryExpressionParser {
private final List<Element> elements = new ArrayList<>();
private final Stack<Query> querys = new Stack<>();
private final Stack<Element> operates = new Stack<>();
/**
* 解析查询表达式,生成Lucene Query对象
*
* @return Lucene query
*/
private Query parseExp(String expression) {
Query lucenceQuery = null;
if (expression != null && !"".equals(expression.trim())) {
try {
// 文法解析
this.splitElements(expression);
// 语法解析
this.parseSyntax();
if (this.querys.size() == 1) {
lucenceQuery = this.querys.pop();
} else {
throw new IllegalStateException("表达式异常: 缺少逻辑操作符 或 括号缺失");
}
} finally {
elements.clear();
querys.clear();
operates.clear();
}
}
return lucenceQuery;
}
/**
* 表达式文法解析
*/
private void splitElements(String expression) {
if (expression == null) {
return;
}
Element currentElement = null;
char[] expChars = expression.toCharArray();
for (char expChar : expChars) {
switch (expChar) {
case '&':
if (currentElement == null) {
currentElement = new Element();
currentElement.type = '&';
currentElement.append(expChar);
} else if (currentElement.type == '&') {
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
} else if (currentElement.type == '\'') {
currentElement.append(expChar);
} else {
this.elements.add(currentElement);
currentElement = new Element();
currentElement.type = '&';
currentElement.append(expChar);
}
break;
case '|':
if (currentElement == null) {
currentElement = new Element();
currentElement.type = '|';
currentElement.append(expChar);
} else if (currentElement.type == '|') {
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
} else if (currentElement.type == '\'') {
currentElement.append(expChar);
} else {
this.elements.add(currentElement);
currentElement = new Element();
currentElement.type = '|';
currentElement.append(expChar);
}
break;
case '-':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = '-';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case '(':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = '(';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case ')':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = ')';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case ':':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = ':';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case '=':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = '=';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case ' ':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
} else {
this.elements.add(currentElement);
currentElement = null;
}
}
break;
case '\'':
if (currentElement == null) {
currentElement = new Element();
currentElement.type = '\'';
} else if (currentElement.type == '\'') {
this.elements.add(currentElement);
currentElement = null;
} else {
this.elements.add(currentElement);
currentElement = new Element();
currentElement.type = '\'';
}
break;
case '[':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = '[';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case ']':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = ']';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case '{':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = '{';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case '}':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = '}';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
case ',':
if (currentElement != null) {
if (currentElement.type == '\'') {
currentElement.append(expChar);
continue;
} else {
this.elements.add(currentElement);
}
}
currentElement = new Element();
currentElement.type = ',';
currentElement.append(expChar);
this.elements.add(currentElement);
currentElement = null;
break;
default:
if (currentElement == null) {
currentElement = new Element();
currentElement.type = 'F';
currentElement.append(expChar);
} else if (currentElement.type == 'F') {
currentElement.append(expChar);
} else if (currentElement.type == '\'') {
currentElement.append(expChar);
} else {
this.elements.add(currentElement);
currentElement = new Element();
currentElement.type = 'F';
currentElement.append(expChar);
}
}
}
if (currentElement != null) {
this.elements.add(currentElement);
}
}
/**
* 语法解析
*/
private void parseSyntax() {
for (int i = 0; i < this.elements.size(); i++) {
Element e = this.elements.get(i);
if ('F' == e.type) {
Element e2 = this.elements.get(i + 1);
if ('=' != e2.type && ':' != e2.type) {
throw new IllegalStateException("表达式异常: = 或 : 号丢失");
}
Element e3 = this.elements.get(i + 2);
// 处理 = 和 : 运算
if ('\'' == e3.type) {
i += 2;
if ('=' == e2.type) {
TermQuery tQuery = new TermQuery(new Term(e.toString(), e3.toString()));
this.querys.push(tQuery);
} else {
String keyword = e3.toString();
// SWMCQuery Here
Query _SWMCQuery = SWMCQueryBuilder.create(e.toString(), keyword);
this.querys.push(_SWMCQuery);
}
} else if ('[' == e3.type || '{' == e3.type) {
i += 2;
// 处理 [] 和 {}
LinkedList<Element> eQueue = new LinkedList<>();
eQueue.add(e3);
for (i++; i < this.elements.size(); i++) {
Element eN = this.elements.get(i);
eQueue.add(eN);
if (']' == eN.type || '}' == eN.type) {
break;
}
}
// 翻译RangeQuery
Query rangeQuery = this.toTermRangeQuery(e, eQueue);
this.querys.push(rangeQuery);
} else {
throw new IllegalStateException("表达式异常:匹配值丢失");
}
} else if ('(' == e.type) {
this.operates.push(e);
} else if (')' == e.type) {
boolean doPop = true;
while (doPop && !this.operates.empty()) {
Element op = this.operates.pop();
if ('(' == op.type) {
doPop = false;
} else {
Query q = toBooleanQuery(op);
this.querys.push(q);
}
}
} else {
if (this.operates.isEmpty()) {
this.operates.push(e);
} else {
boolean doPeek = true;
while (doPeek && !this.operates.isEmpty()) {
Element eleOnTop = this.operates.peek();
if ('(' == eleOnTop.type) {
doPeek = false;
this.operates.push(e);
} else if (compare(e, eleOnTop) == 1) {
this.operates.push(e);
doPeek = false;
} else if (compare(e, eleOnTop) == 0) {
Query q = toBooleanQuery(eleOnTop);
this.operates.pop();
this.querys.push(q);
} else {
Query q = toBooleanQuery(eleOnTop);
this.operates.pop();
this.querys.push(q);
}
}
if (doPeek && this.operates.empty()) {
this.operates.push(e);
}
}
}
}
while (!this.operates.isEmpty()) {
Element eleOnTop = this.operates.pop();
Query q = toBooleanQuery(eleOnTop);
this.querys.push(q);
}
}
/**
* 根据逻辑操作符,生成BooleanQuery
*/
private Query toBooleanQuery(Element op) {
if (this.querys.size() == 0) {
return null;
}
BooleanQuery.Builder resultQuery = new BooleanQuery.Builder();
if (this.querys.size() == 1) {
return this.querys.get(0);
}
Query q2 = this.querys.pop();
Query q1 = this.querys.pop();
if ('&' == op.type) {
if (q1 != null) {
if (q1 instanceof BooleanQuery) {
List<BooleanClause> clauses = ((BooleanQuery) q1).clauses();
if (clauses.size() > 0
&& clauses.get(0).getOccur() == Occur.MUST) {
for (BooleanClause c : clauses) {
resultQuery.add(c);
}
} else {
resultQuery.add(q1, Occur.MUST);
}
} else {
// q1 instanceof TermQuery
// q1 instanceof TermRangeQuery
// q1 instanceof PhraseQuery
// others
resultQuery.add(q1, Occur.MUST);
}
}
if (q2 != null) {
if (q2 instanceof BooleanQuery) {
List<BooleanClause> clauses = ((BooleanQuery) q2).clauses();
if (clauses.size() > 0
&& clauses.get(0).getOccur() == Occur.MUST) {
for (BooleanClause c : clauses) {
resultQuery.add(c);
}
} else {
resultQuery.add(q2, Occur.MUST);
}
} else {
// q1 instanceof TermQuery
// q1 instanceof TermRangeQuery
// q1 instanceof PhraseQuery
// others
resultQuery.add(q2, Occur.MUST);
}
}
} else if ('|' == op.type) {
if (q1 != null) {
if (q1 instanceof BooleanQuery) {
List<BooleanClause> clauses = ((BooleanQuery) q1).clauses();
if (clauses.size() > 0
&& clauses.get(0).getOccur() == Occur.SHOULD) {
for (BooleanClause c : clauses) {
resultQuery.add(c);
}
} else {
resultQuery.add(q1, Occur.SHOULD);
}
} else {
// q1 instanceof TermQuery
// q1 instanceof TermRangeQuery
// q1 instanceof PhraseQuery
// others
resultQuery.add(q1, Occur.SHOULD);
}
}
if (q2 != null) {
if (q2 instanceof BooleanQuery) {
List<BooleanClause> clauses = ((BooleanQuery) q2).clauses();
if (clauses.size() > 0
&& clauses.get(0).getOccur() == Occur.SHOULD) {
for (BooleanClause c : clauses) {
resultQuery.add(c);
}
} else {
resultQuery.add(q2, Occur.SHOULD);
}
} else {
// q2 instanceof TermQuery
// q2 instanceof TermRangeQuery
// q2 instanceof PhraseQuery
// others
resultQuery.add(q2, Occur.SHOULD);
}
}
} else if ('-' == op.type) {
if (q1 == null || q2 == null) {
throw new IllegalStateException("表达式异常:SubQuery 个数不匹配");
}
if (q1 instanceof BooleanQuery) {
List<BooleanClause> clauses = ((BooleanQuery) q1).clauses();
if (clauses.size() > 0) {
for (BooleanClause c : clauses) {
resultQuery.add(c);
}
} else {
resultQuery.add(q1, Occur.MUST);
}
} else {
// q1 instanceof TermQuery
// q1 instanceof TermRangeQuery
// q1 instanceof PhraseQuery
// others
resultQuery.add(q1, Occur.MUST);
}
resultQuery.add(q2, Occur.MUST_NOT);
}
return resultQuery.build();
}
/**
* 组装TermRangeQuery
*/
private TermRangeQuery toTermRangeQuery(Element fieldNameEle, LinkedList<Element> elements) {
boolean includeFirst;
boolean includeLast;
String firstValue;
String lastValue = null;
// 检查第一个元素是否是[或者{
Element first = elements.getFirst();
if ('[' == first.type) {
includeFirst = true;
} else if ('{' == first.type) {
includeFirst = false;
} else {
throw new IllegalStateException("表达式异常");
}
// 检查最后一个元素是否是]或者}
Element last = elements.getLast();
if (']' == last.type) {
includeLast = true;
} else if ('}' == last.type) {
includeLast = false;
} else {
throw new IllegalStateException("表达式异常, RangeQuery缺少结束括号");
}
if (elements.size() < 4 || elements.size() > 5) {
throw new IllegalStateException("表达式异常, RangeQuery 错误");
}
// 读出中间部分
Element e2 = elements.get(1);
if ('\'' == e2.type) {
firstValue = e2.toString();
//
Element e3 = elements.get(2);
if (',' != e3.type) {
throw new IllegalStateException("表达式异常, RangeQuery缺少逗号分隔");
}
//
Element e4 = elements.get(3);
if ('\'' == e4.type) {
lastValue = e4.toString();
} else if (e4 != last) {
throw new IllegalStateException("表达式异常,RangeQuery格式错误");
}
} else if (',' == e2.type) {
firstValue = null;
//
Element e3 = elements.get(2);
if ('\'' == e3.type) {
lastValue = e3.toString();
} else {
throw new IllegalStateException("表达式异常,RangeQuery格式错误");
}
} else {
throw new IllegalStateException("表达式异常, RangeQuery格式错误");
}
assert firstValue != null;
assert lastValue != null;
return new TermRangeQuery(fieldNameEle.toString(), new BytesRef(firstValue), new BytesRef(lastValue), includeFirst, includeLast);
}
/**
* 比较操作符优先级
*/
private int compare(Element e1, Element e2) {
if ('&' == e1.type) {
if ('&' == e2.type) {
return 0;
} else {
return 1;
}
} else if ('|' == e1.type) {
if ('&' == e2.type) {
return -1;
} else if ('|' == e2.type) {
return 0;
} else {
return 1;
}
} else {
if ('-' == e2.type) {
return 0;
} else {
return -1;
}
}
}
/**
* 表达式元素(操作符、FieldName、FieldValue)
*
* @author linliangyi
* May 20, 2010
*/
private static class Element {
char type = 0;
StringBuffer eleTextBuff;
Element() {
eleTextBuff = new StringBuffer();
}
void append(char c) {
this.eleTextBuff.append(c);
}
public String toString() {
return this.eleTextBuff.toString();
}
}
public static void main(String[] args) {
IKQueryExpressionParser parser = new IKQueryExpressionParser();
String ikQueryExp = "(id='ABcdRf' && date:{'20010101','20110101'} && keyword:'魔兽中国') || (content:'KSHT-KSH-A001-18' || ulr='www.ik.com') - name:'林良益'";
Query result = parser.parseExp(ikQueryExp);
System.out.println(result);
}
}
================================================
FILE: src/main/java/org/wltea/analyzer/query/SWMCQueryBuilder.java
================================================
/*
* IK 中文分词 版本 8.5.0
* IK Analyzer release 8.5.0
*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* 源代码由林良益(linliangyi2005@gmail.com)提供
* 版权声明 2012,乌龙茶工作室
* provided by Linliangyi and copyright 2012 by Oolong studio
*
* 8.5.0版本 由 Magese (magese@live.cn) 更新
* release 8.5.0 update by Magese(magese@live.cn)
*
*/
package org.wltea.analyzer.query;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.queryparser.classic.ParseException;
import org.apache.lucene.queryparser.classic.QueryParser;
import org.apache.lucene.search.Query;
import org.wltea.analyzer.core.IKSegmenter;
import org.wltea.analyzer.core.Lexeme;
import java.io.IOException;
import java.io.StringReader;
import java.util.ArrayList;
import java.util.List;
/**
* Single Word Multi Char Query Builder
* IK分词算法专用
*
* @author linliangyi
*/
@SuppressWarnings("unused")
class SWMCQueryBuilder {
/**
* 生成SWMCQuery
*
* @return Lucene Query
*/
static Query create(String fieldName, String keywords) {
if (fieldName == null || keywords == null) {
throw new IllegalArgumentException("参数 fieldName 、 keywords 不能为null.");
}
// 1.对keywords进行分词处理
List<Lexeme> lexemes = doAnalyze(keywords);
// 2.根据分词结果,生成SWMCQuery
return getSWMCQuery(fieldName, lexemes);
}
/**
* 分词切分,并返回结链表
*/
private static List<Lexeme> doAnalyze(String keywords) {
List<Lexeme> lexemes = new ArrayList<>();
IKSegmenter ikSeg = new IKSegmenter(new StringReader(keywords), true);
try {
Lexeme l;
while ((l = ikSeg.next()) != null) {
lexemes.add(l);
}
} catch (IOException e) {
e.printStackTrace();
}
return lexemes;
}
/**
* 根据分词结果生成SWMC搜索
*/
private static Query getSWMCQuery(String fieldName, List<Lexeme> lexemes) {
// 构造SWMC的查询表达式
StringBuilder keywordBuffer = new StringBuilder();
// 精简的SWMC的查询表达式
StringBuilder keywordBuffer_Short = new StringBuilder();
// 记录最后词元长度
int lastLexemeLength = 0;
// 记录最后词元结束位置
int lastLexemeEnd = -1;
int shortCount = 0;
int totalCount = 0;
for (Lexeme l : lexemes) {
totalCount += l.getLength();
// 精简表达式
if (l.getLength() > 1) {
keywordBuffer_Short.append(' ').append(l.getLexemeText());
shortCount += l.getLength();
}
if (lastLexemeLength == 0) {
keywordBuffer.append(l.getLexemeText());
} else if (lastLexemeLength == 1 && l.getLength() == 1
&& lastLexemeEnd == l.getBeginPosition()) {// 单字位置相邻,长度为一,合并)
keywordBuffer.append(l.getLexemeText());
} else {
keywordBuffer.append(' ').append(l.getLexemeText());
}
lastLexemeLength = l.getLength();
lastLexemeEnd = l.getEndPosition();
}
// 借助lucene queryparser 生成SWMC Query
QueryParser qp = new QueryParser(fieldName, new StandardAnalyzer());
qp.setAutoGeneratePhraseQueries(false);
qp.setDefaultOperator(QueryParser.AND_OPERATOR);
if ((shortCount * 1.0f / totalCount) > 0.5f) {
try {
return qp.parse(keywordBuffer_Short.toString());
} catch (ParseException e) {
e.printStackTrace();
}
} else {
if (keywordBuffer.length() > 0) {
try {
return qp.parse(keywordBuffer.toString());
} catch (ParseException e) {
e.printStackTrace();
}
}
}
return null;
}
}
================================================
FILE: src/main/resources/IKAnalyzer.cfg.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment>IK Analyzer 扩展配置</comment>
<!-- 配置是否加载默认词典 -->
<entry key="use_main_dict">true</entry>
<!-- 配置自己的扩展字典,多个用分号分隔 -->
<entry key="ext_dict">ext.dic;</entry>
<!-- 配置自己的扩展停止词字典,多个用分号分隔 -->
<entry key="ext_stopwords">stopword.dic;</entry>
</properties>
================================================
FILE: src/main/resources/dict/main2012.dic
================================================
他
你
切
她
我
手
有
的
见
A股
B股
H股
K线
U盘
一丁
一丈
一上
一下
一世
一丙
一业
一丝
一两
一个
一中
一串
一丸
一举
一久
一义
一乐
一书
一买
一事
一些
一交
一产
一亩
一亮
一人
一亿
一仁
一介
一仗
一付
一代
一件
一任
一份
一伍
一伙
一会
一传
一伸
一似
一位
一住
一体
一例
一侧
一俟
一信
一倍
一倒
一倘
一偏
一做
一停
一元
一兆
一克
一党
一兜
一共
一关
一兵
一具
一养
一册
一再
一写
一军
一冲
一冷
一冻
一准
一凉
一出
一击
一刀
一分
一切
一划
一列
一则
一别
一到
一刷
一券
一刹
一刻
一剂
一削
一前
一剑
一剥
一副
一割
一力
一办
一动
一劫
一勺
一包
一匙
一区
一半
一卒
一卖
一卡
一卫
一卷
一厅
一压
一厘
一厢
一去
一又
一叉
一友
一双
一发
一变
一叠
一口
一句
一只
一叫
一台
一右
一叶
一号
一吃
一合
一吊
一同
一名
一后
一吐
一向
一吓
一吞
一吨
一听
一吸
一吹
一吼
一告
一员
一周
一味
一命
一和
一咬
一品
一哭
一啃
一喊
一喝
一回
一团
一国
一圆
一圈
一在
一地
一场
一坐
一块
一垒
一堂
一堆
一堵
一填
一墩
一壁
一声
一壶
一处
一夕
一多
一夜
一夥
一大
一天
一夫
一头
一奇
一奖
一套
一女
一好
一如
一妇
一妻
一子
一孔
一字
一存
一孝
一季
一守
一宗
一定
一宝
一审
一客
一室
一家
一寨
一寸
一对
一封
一将
一尊
一小
一少
一尝
一就
一尺
一尾
一局
一层
一届
一屏
一展
一山
一岁
一左
一己
一巷
一市
一师
一帖
一带
一帧
一席
一帮
一幅
一幕
一幢
一干
一年
一并
一床
一应
一店
一度
一座
一庹
一开
一式
一张
一弯
一弹
一当
一往
一征
一径
一律
一得
一心
一忙
一忠
一念
一忽
一怒
一怔
一总
一息
一惊
一想
一意
一愣
一成
一战
一截
一户
一房
一所
一扇
一手
一扎
一打
一扔
一扣
一扫
一扭
一扯
一批
一找
一技
一把
一抓
一抖
一折
一抛
一报
一披
一抬
一抱
一抹
一抽
一拆
一拉
一拍
一拐
一拖
一招
一拜
一拨
一拳
一拼
一拽
一挂
一指
一按
一挡
一挥
一振
一挺
一挽
一捅
一捆
一捋
一捺
一掀
一掉
一掌
一排
一探
一推
一提
一插
一搏
一搞
一摆
一摇
一摔
一摞
一摸
一撇
一撕
一播
一撮
一支
一收
一改
一攻
一放
一数
一敲
一整
一敷
一文
一斑
一斤
一斩
一断
一新
一方
一旁
一旅
一族
一无
一日
一旦
一早
一旬
一时
一明
一星
一春
一是
一昼
一晃
一晒
一晚
一晤
一智
一暗
一曲
一月
一有
一服
一望
一朝
一期
一本
一朵
一杆
一村
一束
一杠
一条
一来
一杯
一板
一枚
一枝
一枪
一架
一柄
一柜
一查
一栋
一栏
一树
一株
一样
一根
一格
一案
一桌
一档
一桩
一桶
一梭
一梯
一棉
一棍
一棒
一棵
一楼
一概
一樘
一横
一次
一款
一正
一步
一死
一段
一比
一毛
一毫
一民
一气
一氧
一水
一江
一池
一汽
一沉
一泡
一波
一泼
一洗
一洞
一派
一流
一测
一浪
一涂
一混
一添
一清
一湖
一滑
一滩
一滴
一潭
一火
一炒
一炖
一炝
一炮
一点
一烘
一烤
一烫
一热
一焖
一照
一煨
一煮
一熟
一爱
一父
一爿
一片
一版
一牙
一物
一牵
一状
一环
一现
一班
一球
一瓢
一瓣
一瓶
一生
一用
一甩
一甲
一男
一画
一番
一病
一瘦
一瘸
一盅
一盆
一盏
一盒
一盖
一盘
一目
一盯
一直
一省
一看
一眨
一眼
一着
一睡
一睹
一瞄
一瞥
一瞧
一瞬
一短
一矮
一石
一码
一砍
一破
一砸
一碗
一碟
一碰
一磅
一磕
一礼
一票
一禁
一种
一科
一秒
一程
一稿
一空
一窍
一窝
一竖
一站
一章
一端
一竿
一笑
一笔
一等
一筐
一筒
一筹
一签
一算
一管
一箩
一箱
一篇
一篓
一篮
一簇
一米
一类
一粒
一糊
一系
一紧
一红
一约
一级
一纸
一线
一练
一组
一经
一绝
一统
一绺
一缕
一缘
一缩
一缸
一罐
一网
一罩
一群
一翻
一老
一者
一联
一聚
一股
一胎
一胖
一脚
一脱
一脸
一腔
一腿
一臂
一致
一舀
一般
一船
一艇
一艘
一色
一节
一茬
一草
一药
一营
一行
一街
一表
一袋
一被
一装
一要
一见
一览
一觉
一角
一触
一言
一计
一订
一议
一记
一讲
一词
一试
一语
一说
一读
一课
一调
一贫
一贯
一赢
一走
一起
一超
一趟
一足
一跃
一跌
一跟
一跤
一跨
一路
一跳
一踏
一踢
一蹭
一蹲
一身
一躲
一躺
一车
一转
一轮
一软
一轰
一轻
一辆
一辈
一辙
一边
一过
一近
一进
一连
一迭
一迳
一退
一途
一通
一遍
一道
一遭
一遮
一邻
一部
一酸
一里
一重
一量
一针
一钱
一铲
一锁
一锅
一错
一锤
一锭
一键
一锹
一镇
一镑
一镶
一长
一门
一闪
一问
一间
一闹
一队
一防
一阵
一阶
一院
一隅
一隔
一集
一震
一霎
一露
一霸
一青
一面
一鞭
一页
一顶
一顷
一项
一顿
一领
一颗
一题
一飞
一餐
一饱
一首
一马
一高
一齐
丁一
丁丁
丁上
丁下
丁丑
丁东
丁亥
丁俨
丁克
丁典
丁冬
丁勉
丁午
丁卡
丁卯
丁同
丁坚
丁坝
丁基
丁壮
丁子
丁字
丁寅
丁尼
丁岚
丁巳
丁当
丁忧
丁怡
丁戌
丁未
丁游
丁炔
丁点
丁烯
丁烷
丁玲
丁班
丁珰
丁申
丁男
丁磊
丁种
丁税
丁等
丁级
丁艰
丁薇
丁辰
丁酉
丁酮
丁酸
丁醇
丁醛
丁雨
丁零
丁青
丁页
丁项
丁香
七一
七七
七下
七世
七个
七中
七五
七人
七亿
七代
七位
七倍
七元
七八
七公
七出
七分
七划
七区
七古
七号
七员
七品
七哥
七喜
七回
七团
七国
七圈
七堵
七声
七夕
七大
七天
七套
七孔
七宝
七寸
七对
七尺
七层
七届
七巷
七年
七度
七座
七弟
七彩
七律
七情
七成
七折
七拳
七排
七支
七日
七旬
七时
七星
七景
七月
七条
七杯
七枝
七格
七桶
七楼
七次
七步
七段
七派
七滴
七点
七爷
七片
七百
七盒
七盘
七票
七种
七秒
七窍
七站
七笔
七篇
七级
七线
七绝
七美
七色
七节
七行
七袋
七角
七言
七路
七辆
七通
七邻
七部
七重
七雄
七音
七题
万一
万丈
万世
万乘
万事
万人
万亿
万代
万件
万份
万伏
万众
万位
万余
万佳
万俟
万倍
万元
万全
万分
万劫
万勿
万千
万华
万博
万卷
万历
万县
万双
万变
万古
万名
万向
万吨
万国
万圆
万圭
万场
万块
万处
万夫
万头
万姓
万字
万宁
万安
万宝
万家
万寿
万山
万岁
万峦
万年
万幸
万度
万恶
万户
万把
万拱
万斤
万方
万无
万春
万有
万望
万机
万条
万桶
万次
万步
万死
万段
万民
万源
万点
万物
万状
万用
万盛
万码
万福
万种
万端
万箱
万籁
万米
万维
万胜
万能
万般
万芳
万荣
万行
万言
万象
万贯
万载
万辆
万达
万通
万道
万邦
万部
万里
万重
万金
万钧
万锭
万隆
万难
万顷
万顺
万马
丈人
丈夫
丈母
丈量
三万
三上
三下
三不
三专
三世
三丙
三两
三个
三中
三义
三乙
三九
三乱
三井
三亚
三产
三人
三亿
三仁
三从
三代
三件
三任
三份
三伍
三伏
三优
三会
三伯
三位
三信
三倍
三元
三光
三克
三党
三公
三关
三具
三军
三分
三利
三制
三副
三包
三北
三区
三原
三叉
三反
三叠
三口
三句
三只
三叶
三合
三同
三名
三向
三和
三品
三围
三国
三堆
三堰
三塔
三塘
三复
三夏
三多
三夜
三头
三套
三好
三姑
三姓
三委
三子
三字
三孝
三季
三学
三定
三宝
三客
三害
三家
三寸
三对
三小
三尺
三局
三层
三届
三山
三岁
三峡
三巷
三师
三年
三废
三度
三座
三建
三式
三张
三弦
三强
三志
三态
三怕
三思
三性
三总
三愿
三成
三战
三截
三户
三房
三才
三打
三拍
三振
三掌
三排
三支
三教
三方
三族
三无
三日
三时
三明
三星
三春
三昧
三是
三晋
三晚
三智
三更
三替
三月
三朝
三期
三木
三杠
三条
三杯
三板
三极
三枝
三株
三样
三格
三桥
三桩
三棉
三棱
三棵
三楼
三次
三正
三步
三段
三毛
三民
三水
三江
三河
三沿
三法
三洋
三流
三涂
三湖
三点
三焦
三熟
三爷
三版
三牲
三玄
三环
三班
三瓣
三生
三甲
三界
三略
三皇
三皈
三盏
三盒
三相
三眼
三碗
三礼
三禁
三秋
三种
三科
三秒
三秦
三穗
三站
三章
三等
三箱
三类
三精
三级
三纲
三线
三统
三维
三缸
三美
三老
三者
三联
三聚
三股
三胎
三能
三脚
三自
三色
三节
三芝
三荣
三菱
三藏
三行
三街
三袋
三西
三角
三讲
三证
三读
三课
三资
三走
三路
三轮
三轻
三边
三连
三通
三遍
三部
三都
三重
三野
三金
三针
三钢
三钱
三锅
三镇
三门
三间
三队
三阳
三阵
三阶
三陪
三集
三面
三页
三项
三顾
三频
三颗
三风
三餐
三高
三鲜
三麦
上万
上下
上世
上个
上举
上乘
上书
上了
上交
上京
上人
上亿
上代
上任
上会
上传
上位
上体
上佳
上例
上供
上元
上光
上党
上关
上兵
上册
上农
上冲
上冻
上刑
上划
上列
上到
上前
上劲
上勤
上区
上匾
上千
上升
上午
上半
上卷
上原
上去
上变
上口
上古
上台
上叶
上司
上吊
上告
上周
上品
上回
上国
上图
上圈
上地
上场
上坐
上坟
上坡
上坪
上垒
上堂
上士
上声
上夜
上天
上头
上奏
上套
上好
上季
上学
上官
上客
上家
上宾
上将
上尉
上层
上屈
上届
上屏
上属
上山
上岗
上岛
上岸
上峰
上工
上市
上帐
上帖
上帝
上席
上年
上床
上座
上廉
上式
上弦
上弹
上当
上影
上得
上心
上思
上成
上战
上房
上手
上托
上扬
上批
上报
上排
上接
上摊
上摸
上操
上文
上方
上旋
上日
上旬
上昆
上明
上映
上晃
上智
上月
上有
上朝
上期
上机
上杉
上李
上条
上来
上杭
上林
上标
上栏
上树
上校
上格
上桅
上框
上桌
上档
上梁
上楼
上榜
上檐
上次
上款
上段
上水
上汤
上汽
上油
上流
上浆
上浮
上海
上涨
上清
上渡
上游
上溢
上溯
上漆
上演
上潮
上火
上灯
上点
上焦
上照
上片
上牌
上犹
上环
上班
上画
上界
上略
上瘾
上百
上皮
上盘
上相
上真
上眼
上着
上知
上石
上礼
上税
上空
上站
上章
上端
上第
上等
上策
上签
上算
上篇
上篮
上簇
上粪
上紧
上级
上纲
上线
上缘
上缴
上网
上翘
上联
上肉
上肢
上肥
上脘
上脸
上膘
上膛
上臂
上自
上至
上船
上色
上节
上苍
上茶
上药
上菜
上蔡
上虞
上蜡
上行
上街
上衣
上表
上装
上角
上解
上言
上计
上访
上证
上诉
上说
上课
上调
上谕
上账
上货
上起
上超
上路
上身
上车
上轨
上载
上轿
上辈
上边
上达
上过
上进
上述
上选
上道
上邦
上部
上釉
上野
上金
上钢
上钩
上铺
上锁
上错
上镜
上门
上闩
上阙
上阵
上限
上院
上集
上面
上鞋
上页
上项
上颌
上颚
上额
上风
上饶
上首
上香
上马
上驷
上髎
上高
下一
下下
下不
下世
下个
下为
下乘
下乡
下书
下了
下井
下人
下代
下令
下任
下传
下位
下体
下余
下作
下例
下侧
下倾
下元
下光
下关
下册
下冲
下凡
下出
下刀
下划
下列
下到
下剩
下力
下劲
下勺
下区
下午
下半
下单
下卷
下厂
下压
下厨
下去
下发
下口
下句
下召
下台
下叶
下同
下周
下咽
下品
下唇
下喙
下回
下图
下土
下在
下地
下场
下坠
下坡
下垂
下堂
下堕
下士
下处
下头
下女
下奶
下好
下嫁
下子
下存
下季
下学
下完
下官
下定
下家
下层
下届
下属
下山
下岗
下工
下巴
下市
下帖
下年
下床
下底
下店
下座
下式
下弦
下得
下怀
下情
下愚
下成
下户
下房
下手
下拉
下拜
下拨
下挫
下排
下探
下接
下推
下摆
下操
下放
下文
下料
下方
下旋
下旬
下月
下有
下朝
下期
下木
下机
下来
下枋
下柬
下标
下树
下格
下框
下档
下桥
下棋
下楼
下榻
下欠
下次
下款
下步
下段
下毒
下民
下气
下水
下江
下沉
下河
下油
下泄
下法
下注
下泻
下派
下流
下浮
下海
下港
下游
下滑
下潮
下炕
下片
下牙
下狱
下班
下生
下田
下界
下略
下疳
下痢
下痿
下盘
下直
下相
下着
下矿
下碗
下礼
下种
下移
下站
下章
下端
下笔
下第
下等
下策
下签
下管
下箸
下篇
下级
下线
下缘
下网
下联
下聘
下肉
下肚
下肢
下脘
下脚
下脣
下腹
下膊
下臣
下自
下至
下船
下药
下菜
下落
下葬
下蛋
下行
下表
下袅
下装
下襬
下角
下设
下诏
下课
下调
下账
下贱
下走
下起
下跌
下跪
下蹲
下身
下车
下载
下轿
下辈
下辖
下边
下达
下过
下述
下遣
下部
下酒
下野
下钓
下钻
下铺
下锅
下键
下门
下问
下阕
下阙
下附
下降
下限
下院
下陷
下集
下雨
下雪
下雹
下雾
下霜
下面
下页
下顿
下颌
下颔
下颚
下额
下风
下饭
下首
下马
下驷
下髎
不一
不下
不与
不严
不中
不丹
不为
不举
不久
不义
不乏
不乐
不买
不乱
不予
不争
不二
不交
不亦
不什
不仁
不仅
不从
不以
不休
不会
不伤
不似
不但
不低
不住
不作
不佞
不佳
不使
不依
不便
不俗
不保
不信
不修
不倒
不借
不倦
不值
不假
不偏
不做
不停
不像
不允
不先
不光
不克
不免
不入
不全
不公
不关
不兴
不具
不兹
不再
不冒
不冷
不准
不减
不凡
不凭
不出
不分
不切
不删
不利
不到
不前
不剩
不力
不加
不动
不升
不单
不占
不厌
不去
不及
不反
不发
不受
不变
不另
不只
不叫
不可
不吃
不合
不吊
不同
不吐
不向
不吝
不含
不听
不吭
不吵
不吻
不周
不和
不哭
不啻
不善
不回
不因
不图
不在
不均
不坏
不坠
不堪
不壹
不备
不复
不外
不多
不够
不大
不太
不失
不奈
不奏
不好
不如
不妙
不妥
不妨
不嫁
不嫌
不孕
不存
不孝
不学
不宁
不守
不安
不完
不定
不宜
不实
不宣
不容
不寐
不察
不对
不封
不将
不小
不少
不就
不尽
不屈
不屑
不属
不巧
不差
不已
不帅
不带
不常
不干
不平
不幸
不应
不廉
不开
不弃
不引
不弱
不强
不归
不当
不往
不待
不很
不得
不必
不忍
不忘
不忙
不忠
不快
不念
不忿
不怀
不怕
不急
不怨
不怪
不恤
不恨
不恭
不息
不悦
不惑
不惜
不惟
不惧
不惮
不惯
不想
不愁
不愉
不意
不感
不愧
不愿
不慌
不慎
不慢
不懂
不懈
不成
不戒
不战
不才
不打
不托
不扣
不扬
不把
不折
不报
不抽
不拔
不拖
不拘
不择
不拿
不挂
不挑
不挡
不振
不捕
不换
不掉
不揍
不提
不揣
不擅
不支
不收
不改
不放
不敌
不敏
不敢
不散
不敬
不敷
不文
不料
不断
不新
不无
不日
不早
不时
不明
不易
不是
不显
不晓
不晚
不智
不暇
不曾
不替
不服
不期
不朽
不杀
不材
不来
不松
不枉
不果
不查
不根
不检
不欲
不止
不正
不死
不比
不毛
不气
不求
不治
不法
不洁
不洗
不流
不浅
不测
不济
不涂
不消
不涨
不涩
不淑
不深
不清
不渝
不满
不漏
不灭
不灵
不点
不烦
不热
不然
不熟
不爱
不爽
不特
不犯
不狂
不独
不玩
不理
不甘
不甚
不甜
不用
不由
不畅
不畏
不留
不痛
不白
不相
不看
不真
不着
不睬
不知
不短
不碍
不碰
不祥
不禁
不离
不移
不稳
不穿
不竭
不端
不笑
不符
不笨
不第
不等
不箕
不算
不管
不累
不繁
不约
不纯
不经
不给
不绝
不缝
不缩
不缺
不置
不羁
不老
不考
不耐
不耻
不肖
不肯
不育
不胜
不能
不脱
不自
不臭
不致
不舍
不良
不花
不苟
不若
不苦
不菲
不落
不薄
不虚
不虞
不行
不衰
不被
不装
不要
不见
不觉
不解
不言
不计
不认
不让
不讲
不讳
不许
不论
不识
不诉
不该
不详
不误
不说
不请
不读
不调
不谈
不谋
不谓
不谙
不象
不豫
不贝
不贞
不负
不败
不贰
不贵
不费
不赀
不赖
不足
不跌
不跑
不跟
不跳
不轨
不轻
不辍
不输
不辞
不过
不近
不还
不进
不远
不迟
不迭
不追
不退
不送
不适
不逃
不逊
不透
不通
不逞
不遂
不遇
不遑
不遗
不避
不配
不酸
不醉
不醒
不重
不钓
不锈
不错
不长
不问
不防
不降
不限
不随
不难
不雅
不需
不露
不静
不靠
不韪
不顺
不须
不顾
不领
不食
不饿
不骑
不高
不黏
不齐
不齿
与与
与人
与会
与共
与其
与君
与否
与国
与她
与它
与总
与我
与日
与格
与此
与谁
与赛
与门
与闻
丐养
丐帮
丑丑
丑事
丑人
丑剧
丑化
丑名
丑女
丑妹
丑态
丑怪
丑恶
丑旦
丑时
丑星
丑样
丑死
丑牛
丑男
丑相
丑类
丑脸
丑行
丑角
丑诋
丑话
丑语
丑闻
丑陋
专一
专上
专业
专为
专书
专事
专于
专人
专任
专使
专供
专修
专函
专刊
专列
专利
专制
专力
专区
专卖
专发
专史
专号
专司
专名
专向
专员
专命
专唱
专在
专场
专士
专守
专宠
专家
专属
专差
专席
专干
专库
专座
专往
专征
专心
专恣
专情
专户
专才
专打
专找
专报
专拜
专拣
专指
专控
专摆
专擅
专收
专攻
专政
专教
专文
专断
专有
专机
专杀
专权
专来
专柜
专栏
专校
专案
专横
专款
专此
专治
专注
专版
专用
专电
专看
专着
专科
专租
专程
专稿
专管
专精
专线
专经
专署
专美
专职
专营
专著
专要
专讯
专论
专设
专访
专诚
专责
专车
专辑
专送
专递
专销
专长
专门
专集
专项
专题
专馆
且不
且为
且住
且听
且慢
且有
且末
且看
且经
且莫
且说
丕业
丕变
丕显
世上
世世
世事
世交
世亲
世人
世仇
世代
世传
世伯
世侄
世俗
世兄
世务
世医
世叔
世变
世嘉
世处
世外
世子
世宗
世家
世尊
世尘
世局
世居
世弊
世弟
世德
世态
世情
世故
世敌
世新
世族
世昌
世界
世盟
世系
世纪
世臣
世行
世袭
世说
世谊
世贸
世运
世道
世间
世面
世风
丘东
丘八
丘北
丘县
丘坟
丘墓
丘墟
丘壑
丘岗
丘疹
丘箭
丘脑
丘陵
丙丁
丙丑
丙亥
丙午
丙卯
丙国
丙基
丙子
丙寅
丙巳
丙戌
丙方
丙未
丙村
丙校
丙炔
丙烯
丙烷
丙申
丙种
丙稀
丙等
丙级
丙纶
丙线
丙肝
丙辰
丙酉
丙酮
丙酸
丙醇
丙醛
丙项
业主
业举
业余
业内
业别
业务
业大
业己
业已
业师
业态
业户
业扩
业报
业界
业经
业绩
业者
业迹
业障
丛丛
丛中
丛书
丛刊
丛刻
丛密
丛山
丛木
丛杂
丛林
丛植
丛珊
丛生
丛聚
丛脞
丛莽
丛葬
丛谈
丛集
东丈
东上
东东
东丰
东临
东为
东主
东乡
东亚
东京
东亭
东佃
东侧
东信
东元
东光
东关
东兴
东到
东加
东势
东北
东区
东升
东半
东华
东单
东南
东厂
东厢
东去
东县
东台
东向
东吴
东周
东四
东园
东土
东坡
东城
东域
东墙
东大
东头
东夷
东孚
东宁
东安
东宝
东宫
东家
东富
东寺
东尼
东山
东岛
东岳
东岸
东峻
东川
东巴
东市
东平
东床
东引
东征
东德
东指
东接
东方
东施
东明
东映
东晋
东有
东来
东桥
东森
东欧
东段
东汉
东江
东汽
东沙
东沟
东河
东洋
东流
东海
东渐
东渡
东港
东游
东湖
东源
东滩
东瀛
东爱
东瓜
东盟
东石
东磁
东移
东突
东站
东端
东笋
东线
东经
东翁
东聊
东联
东胜
东胡
东至
东航
东芝
东莞
东莱
东营
东行
东街
东西
东角
东购
东路
东边
东辽
东进
东道
东邦
东邪
东郊
东部
东郭
东都
东门
东阳
东阿
东陵
东非
东面
东风
东魏
东鹏
丝丝
丝光
丝兰
丝印
丝厂
丝巾
丝布
丝帕
丝带
丝弦
丝料
丝束
丝杠
丝板
丝极
丝棉
丝毫
丝状
丝瓜
丝竹
丝米
丝糕
丝素
丝线
丝织
丝绒
丝结
丝绘
丝绢
丝绳
丝绵
丝绸
丝缕
丝网
丝胶
丝萝
丝虫
丝蝇
丝衣
丝袜
丝质
丝路
丝都
丝锥
丞相
丟了
丟档
丢上
丢下
丢丑
丢了
丢人
丢入
丢分
丢到
丢却
丢去
丢在
丢失
丢帧
丢开
丢弃
丢得
丢手
丢掉
丢掷
丢给
丢置
丢脸
丢词
丢起
丢钱
丢面
两万
两三
两下
两两
两个
两亲
两人
两亿
两代
两仪
两件
两任
两份
两伊
两会
两位
两侧
两便
两倍
两元
两克
两党
两全
两关
两具
两册
两军
两刀
两分
两则
两利
两制
两剂
两包
两千
两半
两卷
两厅
两厢
两双
两口
两句
两只
两可
两台
两叶
两号
两名
两员
两周
两回
两国
两圆
两圈
两地
两场
两块
两基
两堆
两声
两壶
两夜
两大
两天
两头
两套
两女
两委
两季
两审
两客
两家
两对
两封
两尾
两局
两层
两届
两岁
两岸
两市
两师
两席
两年
两广
两度
两座
两式
两张
两弹
两德
两忘
两性
两成
两截
两户
两房
两扇
两手
两打
两批
两把
两抵
两拍
两招
两拨
两拳
两排
两支
两方
两旁
两无
两日
两晋
两晚
两月
两期
两本
两朵
两机
两杆
两杠
两条
两杯
两板
两极
两枚
两枝
两枪
两架
两栋
两栖
两样
两根
两格
两档
两桶
两梯
两棵
两次
两款
两步
两段
两毛
两汉
两江
两河
两法
两派
两浙
两淮
两清
两湖
两滴
两潘
两点
两片
两版
两班
两瓣
两瓶
两用
两男
两百
两盅
两相
两省
两眼
两睡
两码
两碗
两票
两种
两科
两秒
两税
两立
两端
两笔
两筒
两箱
两篇
两类
两粒
两粤
两级
两组
两缸
两翼
两者
两耳
两联
两肋
两肩
两胎
两胜
两脚
两腮
两腿
两臂
两船
两节
两行
两袈
两袋
两袖
两角
两讫
两记
两课
两起
两路
两轮
两辆
两边
两连
两通
两造
两遍
两道
两部
两重
两钱
两锅
两键
两间
两队
两阶
两院
两难
两集
两霸
两面
两页
两项
两颊
两颗
两题
两首
两鬓
严严
严于
严令
严修
严冬
严刑
严办
严加
严厉
严命
严处
严复
严守
严实
严宽
严密
严寒
严察
严峻
严嵩
严师
严律
严惩
严打
严把
严抓
严控
严政
严整
严斥
严明
严查
严格
严正
严治
严法
严父
严禁
严竣
严管
严紧
严纲
严细
严肃
严胜
严苛
严词
严谨
严责
严辞
严酷
严重
严防
严阵
严霜
严颜
丧主
丧乱
丧事
丧亡
丧假
丧偶
丧命
丧夫
丧失
丧妻
丧家
丧尸
丧居
丧志
丧手
丧服
丧母
丧气
丧父
丧生
丧礼
丧胆
丧葬
丧身
丧钟
丧门
个个
个中
个人
个位
个体
个例
个儿
个别
个协
个唱
个头
个子
个字
个展
个度
个性
个把
个数
个旧
个月
个案
个私
个股
个贷
个里
丫丫
丫头
丫嬛
丫子
丫杈
丫环
丫鬟
中一
中三
中上
中下
中专
中世
中东
中举
中义
中乐
中了
中二
中云
中亚
中产
中人
中介
中仑
中代
中价
中伏
中休
中会
中伤
中低
中体
中使
中俄
中保
中信
中值
中储
中允
中元
中共
中兴
中册
中军
中农
中凯
中出
中分
中切
中副
中办
中加
中北
中区
中医
中午
中华
中南
中卫
中印
中厅
中原
中去
中县
中友
中发
中叙
中古
中叶
中号
中听
中和
中唐
中唱
中固
中国
中圈
中土
中场
中坚
中坜
中型
中垦
中城
中堂
中士
中夏
中外
中大
中天
中央
中头
中奖
中套
中委
中子
中学
中宁
中富
中导
中封
中将
中尉
中小
中就
中局
中层
中山
中岛
中岳
中川
中州
中巴
中师
中常
中幔
中幡
中平
中年
中广
中府
中度
中庭
中庸
中式
中弹
中彩
中影
中德
中心
中性
中情
中意
中戏
中所
中技
中报
中招
中拮
中拳
中指
中捷
中排
中提
中支
中放
中文
中断
中新
中方
中旅
中日
中旬
中景
中暑
中曾
中最
中有
中服
中朝
中期
中杏
中材
中村
中杰
中板
中极
中枢
中枪
中柱
中标
中栏
中校
中格
中桅
中档
中桥
中楷
中楼
中欧
中止
中正
中段
中毒
中比
中气
中汇
中江
中沙
中油
中泉
中法
中波
中注
中泰
中洲
中派
中流
中海
中渎
中渚
中港
中游
中演
中火
中灶
中点
中焦
中牟
中环
中班
中生
中用
中田
中男
中甸
中百
中盘
中直
中省
中看
中知
中短
中秋
中科
中程
中稻
中空
中立
中站
中等
中策
中签
中箭
中篇
中粗
中级
中纬
中纺
中纽
中线
中经
中统
中继
中缀
中缝
中网
中置
中美
中考
中耕
中耳
中职
中联
中肯
中胡
中脑
中脘
中腹
中航
中苏
中苑
中英
中药
中菜
中菲
中营
中落
中葡
中葯
中行
中表
中被
中装
中裤
中西
中观
中视
中觉
中计
中讯
中讲
中论
中词
中译
中试
中谷
中资
中越
中跟
中路
中转
中轴
中辍
中辰
中进
中远
中选
中途
中速
中道
中邪
中郎
中部
中都
中醒
中量
中钢
中铁
中银
中铺
中锋
中键
中长
中门
中间
中队
中阮
中阳
中院
中隔
中集
中雨
中雪
中非
中靶
中韩
中音
中韶
中频
中风
中餐
中饭
中饱
中马
中高
中魁
中魔
中黄
中齿
丰业
丰乐
丰乳
丰产
丰功
丰华
丰南
丰厚
丰原
丰县
丰台
丰城
丰壤
丰姿
丰宁
丰实
丰富
丰岛
丰年
丰收
丰沛
丰泰
丰润
丰满
丰滨
丰田
丰登
丰盈
丰盛
丰瞻
丰硕
丰碑
丰稔
丰美
丰羽
丰胸
丰腴
丰茂
丰草
丰裕
丰赡
丰足
丰都
丰采
丰镇
丰隆
丰韵
丰顺
丰饶
串上
串串
串休
串会
串供
串列
串口
串台
串号
串味
串城
串岗
串成
串户
串换
串接
串改
串气
串流
串游
串演
串珠
串线
串联
串行
串街
串讲
串话
串起
串连
串通
串铃
串门
串音
串骗
临了
临产
临人
临刑
临利
临别
临到
临危
临去
临县
临场
临城
临夏
临头
临安
临客
临川
临帖
临幸
临床
临建
临快
临战
临拼
临摹
临时
临月
临朐
临朝
临期
临末
临机
临村
临桂
临检
临武
临死
临水
临江
临池
临汾
临沂
临沐
临沧
临沭
临河
临泉
临泽
临洮
临济
临海
临清
临渊
临湖
临湘
临溪
临漳
临潭
临潼
临澧
临猗
临画
临界
临盆
临眺
临着
临睡
临终
临考
临蓐
临行
临街
临西
临视
临走
临近
临邑
临门
临阵
临难
临震
临靠
临颖
临风
临高
丸剂
丸子
丸药
丸髻
丹下
丹东
丹丸
丹丹
丹佛
丹凤
丹剧
丹参
丹寨
丹巴
丹徒
丹心
丹忱
丹方
丹枫
丹桂
丹棱
丹毒
丹江
丹田
丹砂
丹粒
丹红
丹纳
丹荔
丹药
丹诏
丹阳
丹霞
丹青
丹顿
丹麦
为主
为了
为人
为伍
为何
为先
为准
为副
为名
为啥
为官
为害
为师
为恶
为患
为政
为时
为期
为止
为此
为民
为生
为由
为着
为辅
为重
为难
为首
主上
主业
主义
主事
主产
主人
主仆
主从
主件
主任
主伐
主位
主体
主使
主供
主修
主值
主儿
主公
主凶
主刀
主刑
主创
主力
主办
主动
主厨
主句
主叫
主台
主名
主和
主唱
主因
主场
主坝
主城
主墙
主外
主奏
主妇
主委
主婚
主子
主存
主官
主审
主客
主宰
主家
主宾
主导
主将
主峰
主币
主帅
主帆
主席
主干
主库
主张
主意
主戏
主战
主把
主抓
主报
主持
主掌
主控
主推
主攻
主政
主教
主文
主料
主族
主旨
主星
主景
主机
主杀
主权
主板
主枝
主架
主根
主格
主桅
主档
主桥
主楼
主槽
主次
主殿
主母
主治
主流
主演
主潮
主炮
主点
主父
主牌
主犯
主理
主瓣
主监
主盘
主矩
主碑
主祭
主科
主稿
主笔
主管
主粮
主线
主组
主编
主罚
主罪
主群
主考
主脉
主脑
主茎
主菜
主营
主表
主裁
主要
主见
主观
主视
主角
主计
主记
主讲
主诉
主词
主试
主语
主课
主调
主谋
主谓
主路
主轴
主辩
主进
主送
主部
主钩
主键
主长
主队
主震
主面
主音
主页
主项
主顾
主频
主题
主食
丽人
丽台
丽山
丽影
丽日
丽服
丽水
丽江
丽群
丽色
丽莉
丽藻
丽质
丽都
丽靡
丽音
丽风
举世
举个
举为
举了
举事
举人
举例
举借
举债
举兵
举凡
举出
举办
举动
举发
举哀
举国
举头
举好
举子
举家
举手
举报
举抬
举措
举旗
举有
举杯
举析
举枪
举架
举止
举步
举火
举烛
举用
举目
举直
举着
举箸
举组
举荐
举行
举要
举证
举贤
举起
举足
举过
举重
举错
举高
举鼎
乃东
乃兄
乃公
乃尔
乃就
乃弟
乃是
乃曰
乃父
乃祖
乃翁
乃能
乃至
乃蛮
乃见
乃需
久久
久之
久了
久仰
久候
久别
久后
久坐
久存
久居
久已
久慕
久拖
久旱
久暂
久治
久浸
久留
久病
久盼
久等
久经
久跪
久远
久违
久长
久间
久闻
久雨
么儿
么喝
么妹
么子
么弟
么爷
义举
义乌
义仆
义仓
义侠
义兄
义军
义冢
义决
义利
义务
义勇
义卖
义县
义国
义塾
义士
义女
义妈
义子
义学
义工
义师
义庄
义弟
义律
义愤
义战
义捐
义旗
义母
义民
义气
义法
义演
义父
义犬
义理
义生
义田
义美
义肢
义节
义蕴
义行
义警
义诊
义赛
义足
义部
义项
义颌
义风
义马
义齿
之一
之三
之上
之下
之世
之中
之为
之主
之举
之久
之义
之乐
之乡
之书
之乱
之争
之事
之二
之于
之交
之人
之低
之余
之作
之便
之光
之兵
之内
之冠
之冤
之刃
之分
之列
之初
之利
之别
之前
之剑
之力
之功
之劳
之势
之又
之友
之变
之右
之名
之后
之味
之和
之哉
之喜
之国
之在
之地
之城
之墓
之声
之处
之复
之外
之多
之夜
之大
之女
之妙
之始
之嫌
之子
之学
之宝
之实
之害
之家
之屋
之岛
之左
之巨
之差
之年
之影
之徒
之心
之忧
之怨
之恋
之恩
之情
之想
之意
之感
之愤
之慢
之战
之手
之才
之扰
之故
之旁
之旅
之无
之日
之时
之星
之春
之最
之有
之本
之极
之梦
之森
之欢
之欲
之歌
之死
之母
之比
之水
之江
之法
之流
之源
之火
之灾
之爱
之父
之狼
之玉
之王
之珠
之理
之用
之症
之神
之秋
之称
之窗
之类
之约
之罪
之能
之腹
之至
之致
之舞
之苦
之蛙
之行
之见
之言
之计
之论
之证
之词
之误
之说
之请
之谈
之谜
之路
之身
之躯
之辈
之过
之道
之遥
之都
之醒
之长
之门
之闲
之间
之际
之隔
之难
之需
之面
之音
之风
之馀
之首
之高
之龙
乌丘
乌丝
乌丸
乌云
乌亮
乌什
乌兰
乌共
乌发
乌合
乌呼
乌头
乌尔
乌局
乌山
乌巾
乌市
乌恰
乌拉
乌日
乌有
乌木
乌来
乌枣
乌桓
乌桕
乌梅
乌檀
乌江
乌池
乌海
乌涂
乌盟
乌篷
乌纱
乌苏
乌药
乌蓝
乌蛤
乌豆
乌贼
乌达
乌金
乌镇
乌青
乌韭
乌鱼
乌鲳
乌鳢
乌鸡
乌鸦
乌黑
乌龙
乌龟
乍冷
乍听
乍富
乍得
乍暖
乍浦
乍热
乍然
乍现
乍看
乍见
乍读
乎呼
乎噜
乏力
乏味
乏善
乏困
乏指
乏术
乏汽
乏煤
乏色
乏话
乏货
乏顿
乐业
乐乐
乐了
乐事
乐于
乐亭
乐从
乐儿
乐凯
乐利
乐到
乐华
乐厚
乐受
乐句
乐吧
乐命
乐和
乐善
乐器
乐团
乐园
乐土
乐圣
乐坊
乐坛
乐境
乐声
乐天
乐子
乐安
乐官
乐山
乐工
乐师
乐平
乐府
乐律
乐得
乐心
乐意
乐感
乐户
乐手
乐捐
乐施
乐昌
乐曲
乐果
乐歌
乐死
乐段
乐毅
乐池
乐清
乐理
乐着
乐神
乐章
乐群
乐者
乐育
乐腾
乐至
乐舞
乐见
乐观
乐记
乐论
乐调
乐谱
乐趣
乐进
乐迷
乐道
乐邦
乐闻
乐队
乐陵
乐障
乐音
乒乒
乒乓
乒协
乒坛
乓乓
乔丹
乔乔
乔奇
乔奎
乔妆
乔宏
乔峰
乔布
乔庄
乔扮
乔木
乔治
乔石
乔福
乔脑
乔装
乔迁
乖乖
乖僻
乖到
乖巧
乖异
乖张
乖得
乖戾
乖舛
乖觉
乖谬
乖蹇
乖违
乖隔
乖顺
乘上
乘了
乘以
乘便
乘兴
乘具
乘凉
乘到
乘务
乘势
乘号
乘员
乘在
乘坐
乘客
乘幂
乘座
乘得
乘数
乘方
乘机
乘法
乘着
乘积
乘空
乘筏
乘胜
乘船
乘虚
乘警
乘起
乘车
乘轿
乘过
乘间
乘除
乘隙
乘风
乘马
乙丑
乙亥
乙午
乙卯
乙地
乙型
乙基
乙子
乙存
乙寅
乙巳
乙戌
乙方
乙未
乙炔
乙烯
乙烷
乙班
乙申
乙种
乙等
乙类
乙级
乙肝
乙胺
乙脑
乙苯
乙辰
乙酉
乙酰
乙酸
乙醇
乙醚
乙醛
乜嘢
乜斜
乜水
九世
九五
九卿
九原
九台
九员
九品
九圆
九圈
九城
九天
九孔
九宫
九宵
九州
九归
九所
九旬
九月
九柳
九格
九段
九江
九泉
九洲
九派
九流
九班
九瓶
九皋
九窍
九章
九街
九角
九课
九运
九通
九部
九重
九针
九阳
九难
九集
九霄
九颗
九鼎
九龙
乞丐
乞儿
乞命
乞和
乞巧
乞怜
乞恕
乞援
乞求
乞灵
乞粮
乞讨
乞贷
乞降
乞食
也好
也就
也才
也无
也是
也有
也罢
也行
也要
也许
也门
习习
习于
习作
习俗
习军
习好
习字
习定
习尚
习性
习惯
习拳
习文
习服
习染
习武
习气
习水
习用
习练
习艺
习见
习语
习谚
习非
习题
乡丁
乡下
乡乡
乡井
乡亲
乡人
乡企
乡会
乡佬
乡俗
乡党
乡关
乡办
乡勇
乡原
乡友
乡名
乡味
乡土
乡城
乡塾
乡宁
乡宦
乡居
乡心
乡思
乡情
乡愁
乡愿
乡曲
乡村
乡校
乡民
乡气
乡级
乡绅
乡试
乡谈
乡谊
乡贤
乡邮
乡邻
乡里
乡野
乡镇
乡长
乡间
乡音
书上
书丛
书中
书亭
书价
书会
书体
书信
书僮
书内
书册
书写
书函
书刊
书包
书匠
书协
书单
书卡
书卷
书口
书号
书名
书后
书吏
书启
书呆
书品
书商
书圣
书场
书坊
书坛
书城
书堆
书塾
书声
书夹
书契
书套
书学
书家
书局
书屋
书展
书市
书库
书店
书录
书形
书影
书房
书扉
书报
书摊
书摘
书斋
书明
书本
书札
书机
书林
书架
书柜
书标
书案
书桌
书档
书楼
书橱
书款
书法
书海
书牍
书物
书状
书生
书用
书画
书痴
书皮
书目
书眉
书社
书稿
书立
书童
书签
书简
书箧
书箱
书籍
书系
书经
书翰
书肆
书背
书脊
书荒
书虫
书蠹
书袋
书讯
书记
书论
书证
书评
书账
书贩
书费
书迷
书道
书里
书钉
书铺
书院
书集
书面
书页
书馆
书香
书龄
乩童
买一
买下
买个
买主
买书
买买
买了
买些
买价
买光
买入
买到
买办
买单
买卖
买去
买回
买壳
买好
买它
买定
买客
买家
买帐
买张
买得
买成
买户
买房
买手
买断
买方
买春
买来
买气
买淫
买点
买盘
买着
买碟
买票
买空
买米
买给
买者
买药
买菜
买账
买货
买走
买起
买超
买车
买辆
买过
买进
买通
买醉
买鞋
买饭
买马
乱世
乱丝
乱丢
乱乎
乱事
乱交
乱伦
乱估
乱倒
乱做
乱免
乱党
乱兵
乱写
乱军
乱冲
乱切
乱删
乱到
乱刺
乱加
乱动
乱占
乱发
乱叫
乱吃
乱吵
乱吼
乱咬
乱喊
乱喝
乱国
乱图
乱堆
乱套
乱子
乱射
乱局
乱序
乱开
乱弄
乱弹
乱征
乱得
乱性
乱想
乱成
乱扒
乱打
乱扔
乱扯
乱抄
乱拥
乱挤
乱掉
乱推
乱提
乱搞
乱摊
乱摸
乱撞
乱支
乱收
乱改
乱放
乱数
乱杂
乱来
乱民
乱泥
乱流
乱涂
乱涨
乱源
乱滚
乱猜
乱生
乱用
乱画
乱盖
乱相
乱真
乱石
乱码
乱砍
乱神
乱离
乱穿
乱窜
乱答
乱箭
乱糟
乱纪
乱腾
乱臣
乱舞
乱花
乱葬
乱行
乱视
乱记
乱讲
乱设
乱试
乱说
乱调
乱象
乱账
乱购
乱贼
乱走
乱跑
乱蹦
乱转
乱运
乱送
乱逛
乱邦
乱采
乱锯
乱闯
乱闹
乱飞
乱马
乱骂
乱骑
乱鸦
乱麻
乳中
乳交
乳儿
乳光
乳剂
乳化
乳名
乳品
乳夜
乳头
乳娘
乳山
乳峰
乳房
乳晕
乳根
乳母
乳汁
乳沟
乳油
乳液
乳源
乳燕
乳牙
乳牛
乳状
乳猪
乳癌
乳白
乳类
乳粉
乳粥
乳糖
乳糜
乳线
乳罩
乳胶
乳脂
乳腐
乳腺
乳臭
乳草
乳虎
乳质
乳透
乳酒
乳酪
乳酶
乳酸
乳钵
乳饼
乳香
乳鸽
乳黄
乳齿
乾上
乾丝
乾个
乾乾
乾了
乾井
乾亲
乾冰
乾冷
乾净
乾凉
乾县
乾呕
乾咳
乾哥
乾唱
乾嘉
乾嚎
乾地
乾坤
乾妈
乾妹
乾姊
乾娘
乾季
乾宅
乾安
乾弟
乾得
乾性
乾掉
乾旱
乾材
乾杯
乾果
乾枯
乾柴
乾池
乾沟
乾洗
乾涸
乾渴
乾热
乾燥
乾爸
乾爹
乾爽
乾片
乾田
乾瘦
乾瘪
乾癣
乾礼
乾笑
乾等
乾粉
乾粮
乾股
乾脆
乾草
乾菜
乾薪
乾裂
乾贝
乾躁
乾造
乾酪
乾隆
乾雷
乾饭
乾馏
乾鲜
了了
了事
了债
了却
了吗
了吧
了呀
了啦
了嘛
了如
了局
了帐
了当
了得
了悟
了愿
了断
了无
了望
了案
了清
了点
了然
了结
了草
了解
了账
予人
予付
予以
予及
予期
争了
争产
争价
争优
争作
争做
争先
争光
争冠
争出
争创
争利
争办
争功
争取
争吃
争名
争吵
争嘴
争夺
争宠
争强
争当
争得
争战
争执
争抢
争持
争搏
争收
争斗
争权
争气
争求
争点
争相
争着
争端
争胜
争脸
争艳
争衡
争议
争论
争讼
争购
争起
争辨
争辩
争过
争逐
争锋
争长
争闹
争雄
争霸
争鸣
事业
事主
事事
事件
事体
事例
事假
事儿
事先
事关
事典
事前
事功
事务
事势
事发
事变
事后
事宜
事实
事态
事情
事故
事机
事权
事檎
事毕
事物
事理
事由
事略
事相
事端
事败
事迹
事隔
事项
二丁
二七
二万
二三
二上
二下
二专
二世
二个
二中
二乎
二二
二产
二人
二亿
二付
二代
二价
二任
二份
二伍
二伏
二传
二伯
二位
二信
二倍
二元
二八
二关
二具
二分
二划
二则
二副
二动
二区
二十
二千
二半
二叉
二叔
二叠
二句
二台
二号
二名
二员
二哥
二回
二圆
二块
二垒
二声
二夜
二大
二天
二奖
二女
二奶
二妈
二妹
二姊
二姐
二姑
二姨
二娘
二婚
二婶
二嫂
二子
二季
二审
二局
二层
二届
二幅
二年
二度
二式
二弟
二弦
二心
二意
二战
二房
二手
二批
二把
二择
二指
二斤
二无
二日
二是
二晚
二月
二期
二条
二来
二杯
二板
二极
二林
二枚
二栋
二样
二档
二桶
二楼
二次
二步
二段
二氧
二水
二汽
二流
二滩
二滴
二炮
二点
二爷
二爹
二版
二环
二班
二用
二甲
二男
二百
二碗
二种
二科
二秒
二端
二笔
二笼
二等
二筒
二簧
二类
二粒
二级
二线
二维
二绿
二老
二者
二联
二股
二肽
二胡
二舅
二艘
二街
二袋
二话
二课
二路
二轮
二轻
二边
二进
二连
二通
二遍
二郎
二部
二里
二重
二钱
二门
二间
二阶
二难
二集
二页
二顶
二首
二黄
二龙
于七
于于
于今
于伟
于八
于吉
于好
于嫂
于左
于归
于心
于思
于慧
于我
于斯
于是
于此
于江
于洋
于涛
于焉
于田
于禁
于莉
于蓝
于诠
于谦
于连
于都
于阗
于飞
亏了
亏产
亏到
亏困
亏在
亏失
亏少
亏待
亏得
亏心
亏折
亏损
亏掉
亏本
亏格
亏欠
亏死
亏盈
亏短
亏秤
亏空
亏累
亏缺
亏耗
亏蚀
亏负
亏量
云中
云云
云冈
云南
云县
云吞
云和
云团
云图
云块
云天
云头
云安
云室
云尔
云层
云山
云岭
云崖
云彩
云影
云散
云昏
云景
云朵
云杉
云板
云林
云栖
云梢
云梦
云梯
云母
云气
云汉
云河
云浮
云海
云涌
云涛
云淡
云游
云烟
云状
云玲
云石
云端
云篦
云系
云翳
云脚
云航
云英
云表
云豆
云豹
云贵
云量
云锣
云锦
云门
云阳
云际
云雀
云集
云雨
云雾
云霄
云霓
云霞
云霭
云顶
云须
云髻
云鬓
云鬟
云鹤
云龙
互不
互与
互为
互争
互于
互交
互享
互以
互传
互保
互信
互借
互利
互制
互加
互动
互助
互勉
互发
互向
互唱
互喊
互填
互学
互定
互市
互帮
互异
互得
互怜
互惠
互感
互成
互打
互指
互换
互推
互搏
互救
互敬
互斥
互无
互易
互替
互有
互殴
互派
互济
互添
互溶
互点
互爱
互生
互用
互相
互祝
互答
互罚
互联
互聘
互补
互见
互让
互设
互访
互证
互评
互诉
互译
互调
互谅
互谋
互质
互赠
互转
互连
互选
互递
互通
互道
互锁
互问
互闹
五一
五丁
五专
五丙
五两
五中
五串
五乙
五代
五伦
五保
五假
五党
五关
五内
五刀
五刑
五力
五加
五匙
五华
五原
五反
五发
五古
五台
五叶
五味
五商
五四
五圆
五坪
五堰
五堵
五声
五处
五大
五天
五好
五子
五字
五季
五官
五客
五寨
五封
五小
五岭
五岳
五峰
五巷
五师
五帝
五席
五常
五床
五度
五建
五式
五弟
五彩
五律
五感
五戒
五截
五户
五打
五报
五招
五拳
五指
五文
五斗
五方
五星
五晚
五更
五月
五服
五期
五权
五板
五枝
五枢
五栋
五格
五档
五梏
五榖
五欲
五毒
五毛
五河
五洞
五洲
五湖
五爱
五爷
五版
五牛
五环
五班
五甲
五眼
五短
五码
五碗
五福
五科
五笔
五符
五筒
五箱
五米
五素
五线
五经
五绝
五罐
五羊
五联
五股
五胎
五胡
五脏
五自
五船
五色
五节
五荒
五荤
五莲
五营
五蕴
五虎
五行
五街
五衰
五袋
五角
五课
五谷
五起
五轻
五辆
五边
五通
五道
五部
五金
五钱
五铢
五间
五院
五集
五霸
五面
五音
五页
五顶
五项
五颗
五题
五餐
五香
五马
五龙
井上
井下
井位
井佐
井冈
井出
井口
井台
井喷
井场
井坂
井壁
井巷
井底
井径
井村
井架
井水
井沿
井灌
井然
井田
井盐
井盖
井眼
井研
井筒
井绳
井臼
井蛙
井边
井道
井队
井陉
亘古
亚丁
亚世
亚东
亚于
亚伟
亚伦
亚伯
亚光
亚军
亚圣
亚型
亚基
亚太
亚姐
亚当
亚心
亚斯
亚欧
亚氯
亚泰
亚洲
亚热
亚犬
亚瑟
亚盟
亚砜
亚种
亚纲
亚美
亚群
亚联
亚胺
亚行
亚裔
亚视
亚赛
亚运
亚铁
亚铅
亚铜
亚银
亚非
亚鹏
亚麻
亚齐
亚龙
些个
些些
些儿
些小
些少
些微
些许
些须
亟待
亟欲
亟盼
亟需
亟须
亡了
亡佚
亡兄
亡党
亡友
亡命
亡国
亡夫
亡失
亡妹
亡故
亡母
亡灵
亡父
亡者
亡魂
亢奋
亢旱
亢直
亢进
亢阳
交上
交下
交与
交个
交了
交于
交互
交井
交些
交交
交人
交付
交代
交件
交会
交住
交保
交入
交公
交关
交兵
交出
交到
交割
交办
交加
交卷
交卸
交叉
交友
交叠
交口
交合
交响
交售
交回
交困
交城
交大
交好
交媾
交完
交对
交尾
交工
交差
交帐
交并
交底
交往
交待
交心
交恶
交情
交感
交战
交房
交手
交托
交投
交拜
交换
交接
交易
交映
交替
交权
交来
交杯
交椅
交欢
交款
交汇
交活
交流
交涉
交淡
交清
交游
交溃
交火
交点
交班
交用
交由
交电
交界
交瘁
交相
交租
交移
交税
交稿
交管
交粮
交纳
交织
交结
交给
交联
交臂
交融
交行
交角
交警
交谈
交谊
交账
交货
交费
交足
交趾
交辉
交过
交运
交还
交进
交迫
交送
交通
交道
交邮
交配
交钱
交锋
交错
交际
交集
交风
交验
交齐
亥时
亥猪
亦不
亦且
亦会
亦佳
亦即
亦友
亦可
亦同
亦因
亦在
亦对
亦将
亦就
亦属
亦应
亦当
亦得
亦必
亦或
亦按
亦无
亦是
亦有
亦比
亦然
亦称
亦经
亦舒
亦被
亦要
亦还
亦需
亦非
亦须
产业
产中
产乳
产于
产从
产仔
产值
产假
产儿
产出
产前
产区
产卵
产后
产品
产地
产妇
产婆
产子
产床
产房
产期
产权
产油
产流
产物
产状
产生
产界
产科
产程
产米
产粮
产能
产自
产茶
产褥
产道
产量
产钳
产销
产门
产院
产险
产额
亨利
亨特
亨通
亩产
亩数
享乐
享受
享国
享寿
享尽
享年
享有
享服
享用
享福
享誉
京东
京丰
京九
京兆
京剧
京华
京口
京叭
京味
京哈
京城
京官
京山
京师
京广
京府
京戏
京户
京房
京报
京族
京杭
京棉
京求
京沪
京津
京派
京海
京珠
京瓷
京畿
京白
京胡
京腔
京菜
京西
京话
京调
京谷
京郊
京都
京门
京韵
京骨
亭亭
亭午
亭台
亭子
亭桥
亭里
亭长
亮丑
亮丽
亮了
亮儿
亮光
亮出
亮分
亮到
亮堂
亮子
亮底
亮度
亮泽
亮点
亮片
亮牌
亮相
亮着
亮票
亮线
亮绿
亮色
亮节
亮话
亮起
亲丁
亲临
亲了
亲事
亲交
亲亲
亲人
亲代
亲任
亲信
亲兵
亲切
亲历
亲友
亲口
亲启
亲吻
亲呢
亲和
亲善
亲嘴
亲处
亲多
亲夫
亲妈
亲姆
亲威
亲娘
亲子
亲家
亲密
亲展
亲属
亲师
亲往
亲征
亲情
亲戚
亲手
亲抚
亲授
亲收
亲政
亲故
亲族
亲日
亲昵
亲朋
亲本
亲权
亲母
亲洽
亲潮
亲热
亲爱
亲父
亲爹
亲率
亲王
亲生
亲疏
亲眷
亲眼
亲着
亲睦
亲睹
亲知
亲笔
亲缘
亲耳
亲聆
亲职
亲脸
亲自
亲见
亲贵
亲赴
亲身
亲迎
亲近
亲闻
亲随
亲驾
亳县
亳州
亵渎
亵玩
亵臣
亵衣
人丁
人下
人世
人丛
人中
人为
人主
人事
人云
人人
人代
人们
人众
人伦
人体
人保
人偶
人像
人儿
人前
人力
人化
人去
人参
人口
人叫
人名
人后
人吗
人君
人员
人呢
人味
人命
人和
人品
人商
人在
人地
人均
人堆
人墙
人士
人声
人多
人大
人天
人夫
人头
人妖
人子
人字
人学
人定
人家
人寰
人寿
人小
人少
人居
人工
人师
人平
人年
人形
人影
人心
人性
人情
人意
人愧
人愿
人我
人手
人才
人数
人文
人斩
人日
人时
人月
人望
人本
人机
人权
人材
人杰
人极
人样
人格
人梯
人次
人欲
人武
人母
人氏
人民
人气
人治
人流
人浪
人海
人渣
人满
人潮
人烟
人物
人犯
人猿
人瑞
人生
人畜
人皮
人祸
人种
人称
人类
人精
人缘
人缝
人群
人老
人耳
人肉
人脉
人脑
人脸
人臣
人艺
人行
人见
人言
人论
人设
人证
人话
人语
人豪
人质
人贩
人身
人迎
人迹
人选
人造
人道
人部
人间
人防
人阵
人际
人面
人马
人鬼
人鱼
人龙
亻尔
亿万
亿亩
亿元
亿兆
亿利
亿吨
亿唐
亿斤
亿测
什么
什件
什叶
什物
什邡
什锦
仁丹
仁义
仁人
仁信
仁兄
仁化
仁医
仁厚
仁君
仁和
仁子
仁孝
仁学
仁宗
仁寿
仁川
仁布
仁弟
仁德
仁心
仁怀
仁慈
仁政
仁昌
仁术
仁果
仁武
仁爱
仁者
仄仄
仄声
仄韵
仅为
仅举
仅于
仅仅
仅从
仅以
仅供
仅凭
仅剩
仅占
仅及
仅只
仅可
仅在
仅够
仅存
仅对
仅就
仅把
仅指
仅据
仅是
仅有
仅此
仅用
仅管
仅能
仅见
仅足
仅限
仅靠
仆人
仆从
仆倒
仆其
仆参
仆妇
仆役
仆隶
仇人
仇家
仇怨
仇恨
仇恶
仇敌
仇杀
仇视
仇遇
仇隙
今世
今人
今儿
今冬
今华
今名
今后
今周
今夏
今夕
今夜
今天
今宵
今岁
今年
今文
今日
今明
今昔
今春
今是
今晚
今晨
今朝
今期
今次
今欣
今生
今番
今秋
今艺
今草
今译
今起
今音
介乎
介于
介休
介入
介召
介在
介壳
介子
介导
介寿
介怀
介意
介杆
介绍
介胄
介虫
介词
介质
介面
介音
仍不
仍与
仍以
仍会
仍到
仍去
仍可
仍在
仍将
仍应
仍按
仍旧
仍是
仍有
仍未
仍来
仍然
仍照
仍用
仍由
仍称
仍系
仍能
仍要
仍需
仍须
从一
从上
从下
从不
从业
从严
从中
从书
从事
从今
从众
从优
从低
从何
从俗
从债
从兄
从先
从公
从军
从刑
从到
从前
从动
从化
从医
从句
从命
从商
从头
从子
从实
从容
从宽
从小
从属
从师
从征
从快
从戎
从打
从政
从教
从新
从旁
从无
从早
从未
从权
从来
从此
从母
从江
从没
从父
从犯
从略
从盘
从简
从紧
从缓
从缺
从而
从良
从艺
从葬
从警
从起
从轮
从轻
从这
从速
从那
从重
从风
从高
仑背
仓促
仓储
仓卒
仓单
仓容
仓山
仓州
仓库
仓廒
仓廪
仓惶
仓房
仓猝
仓皇
仓颉
仓鼠
仔仔
仔密
仔服
仔猪
仔畜
仔禽
仔细
仔肩
仔鱼
仔鸡
仕奇
仕女
仕官
仕宦
仕进
仕途
他乡
他人
他们
他俩
他因
他国
他处
他家
他律
他指
他方
他日
他用
仗义
仗助
仗势
仗恃
仗持
仗着
仗胆
付上
付下
付与
付丙
付了
付予
付交
付产
付价
付凯
付出
付到
付印
付去
付在
付好
付帐
付强
付彪
付得
付息
付托
付掉
付排
付方
付晶
付有
付来
付梓
付款
付汇
付清
付点
付现
付琼
付着
付给
付讫
付诸
付账
付费
付起
付足
付过
付还
付邮
付酬
付钱
仙丹
仙乐
仙乡
仙人
仙侣
仙儿
仙剑
仙台
仙境
仙女
仙姑
仙子
仙家
仙居
仙山
仙岩
仙岳
仙师
仙府
仙术
仙果
仙桃
仙水
仙游
仙湖
仙界
仙童
仙翁
仙花
仙茅
仙草
仙药
仙踪
仙逝
仙都
仙鹤
仟克
仟村
仟胞
仡佬
代与
代为
代书
代交
代人
代代
代件
代价
代位
代偿
代入
代写
代出
代办
代劳
代县
代发
代取
代号
代名
代售
代唱
代型
代垫
代培
代夫
代子
代工
代币
代序
代庖
代录
代征
代打
代换
代收
代数
代替
代查
代步
代母
代沟
代演
代点
代父
代理
代用
代电
代码
代租
代称
代笔
代签
代管
代耕
代聊
代职
代脉
代行
代表
代言
代订
代议
代词
代课
代谢
代购
代跑
代金
代销
代际
代顿
代领
令严
令亲
令人
令他
令你
令兄
令其
令友
令叔
令名
令坦
令堂
令她
令妹
令姊
令媛
令嫒
令孙
令尊
令岳
令师
令弟
令徒
令您
令慈
令我
令旗
令望
令正
令爱
令牌
令状
令狐
令瑗
令甥
令祖
令箭
令节
令行
令誉
令郎
令郞
令酒
令闻
以上
以下
以东
以为
以久
以于
以作
以使
以供
以便
以候
以免
以其
以内
以军
以利
以前
以北
以南
以及
以右
以后
以备
以外
以太
以定
以对
以左
以往
以待
以情
以我
以故
以方
以是
以晚
以月
以期
以来
以次
以此
以求
以法
以示
以策
以网
以至
以致
以西
以资
以身
以近
以还
以远
以避
以键
以防
以降
以飨
仪仗
仪刑
仪制
仪化
仪和
仪器
仪型
仪容
仪式
仪征
仪态
仪清
仪琳
仪礼
仪节
仪表
仪观
仪轨
仪队
仪陇
仰仗
仰光
仰冲
仰卧
仰天
仰头
仰式
仰慕
仰承
仰望
仰止
仰泳
仰看
仰着
仰给
仰脖
仰观
仰视
仰角
仰赖
仰起
仰靠
仰面
仰韶
仰首
仰高
仲介
仲伯
仲兄
仲冬
仲吕
仲夏
仲孙
仲家
仲尼
仲巴
仲弟
仲春
仲氢
仲秋
仲裁
仲间
仳向
仳离
仵作
件事
件头
件套
件数
件次
价位
价低
价值
价内
价单
价外
价差
价带
价廉
价标
价格
价款
价率
价目
价码
价金
价钱
价额
价高
任一
任丘
任为
任事
任人
任从
任伟
任何
任你
任侠
任便
任兄
任免
任其
任内
任凭
任务
任县
任命
任性
任情
任意
任我
任所
任教
任有
任期
任气
任泉
任满
任用
任由
任职
任脉
任课
任选
份上
份儿
份地
份子
份数
份量
份额
份饭
仿佛
仿冒
仿制
仿办
仿单
仿古
仿字
仿宋
仿建
仿效
仿照
仿生
仿画
仿皮
仿真
仿章
仿纸
仿绢
仿行
仿造
企业
企仰
企划
企及
企图
企待
企慕
企望
企机
企求
企盼
企祷
企管
企鹅
伉俪
伊东
伊人
伊利
伊勒
伊博
伊吹
伊吾
伊妹
伊始
伊宁
伊川
伊循
伊敏
伊文
伊方
伊春
伊曼
伊朗
伊林
伊犁
伊盟
伊籍
伊索
伊红
伊萨
伊蚊
伊豆
伊通
伍万
伍仁
伍佰
伍元
伍总
伍拾
伍顿
伎两
伎俩
伏下
伏侏
伏倒
伏兔
伏兵
伏击
伏到
伏卧
伏在
伏地
伏天
伏妖
伏季
伏安
伏帖
伏惟
伏日
伏旱
伏暑
伏案
伏汛
伏法
伏流
伏牛
伏特
伏生
伏着
伏笔
伏罪
伏羲
伏虎
伏袭
伏诛
伏贴
伏身
伏辨
伏辩
伏首
伐区
伐善
伐木
伐柯
伐树
休业
休书
休会
休假
休克
休兵
休养
休刊
休到
休姆
休学
休宁
休工
休市
休庭
休得
休怪
休息
休想
休憩
休战
休戚
休整
休止
休渔
休班
休眠
休耕
休要
休课
休谟
休闲
众人
众位
众体
众军
众口
众多
众妙
众寡
众怒
众数
众星
众智
众望
众生
众目
众议
众说
众院
优于
优伶
优先
优劣
优势
优化
优厚
优哉
优容
优异
优弧
优待
优惠
优抚
优柔
优流
优渥
优游
优点
优生
优盘
优秀
优种
优等
优絮
优级
优美
优者
优育
优胜
优良
优裕
优质
优越
优选
优遇
优钢
优闲
优雅
伙伴
伙同
伙夫
伙子
伙房
伙犯
伙计
伙食
会上
会下
会与
会东
会个
会中
会为
会了
会于
会付
会众
会会
会使
会做
会停
会儿
会元
会党
会关
会典
会写
会出
会分
会刊
会到
会前
会剿
会办
会加
会务
会动
会升
会占
会卡
会厅
会厌
会去
会友
会发
会受
会叫
会合
会同
会后
会听
会员
会唱
会商
会在
会地
会场
会址
会坏
会堂
会填
会够
会头
会好
会子
会存
会宗
会审
会客
会对
会将
会尽
会展
会师
会帐
会干
会庆
会弹
会当
会得
会徽
会心
会恨
会想
会意
会成
会战
会所
会打
会扣
会把
会报
会抬
会拜
会指
会挑
会掉
会搞
会播
会操
会收
会改
会教
会旗
会昌
会是
会晤
会有
会服
会期
会来
会标
会款
会歌
会比
会水
会泽
会派
会海
会混
会演
会点
会玩
会理
会生
会用
会由
会画
会盟
会看
会着
会社
会种
会稿
会站
会章
会签
会管
会籍
会红
会约
会经
会给
会编
会考
会聚
会脚
会萃
会被
会要
会见
会规
会计
会议
会讲
会诊
会试
会话
会说
会调
会谈
会账
会费
会车
会选
会通
会钞
会钱
会银
会长
会阳
会阴
会附
会集
会面
会风
会餐
会馆
会首
会齐
伛偻
伞兵
伞具
伞包
伞套
伞形
伞投
伞架
伞柄
伞状
伞盖
伞索
伞罩
伞菌
伞衣
伞降
伞面
伟业
伟人
伟力
伟哥
伟大
伟岸
伟康
伟绩
伟航
伟论
传上
传下
传世
传中
传为
传主
传习
传书
传人
传代
传令
传传
传位
传信
传入
传出
传到
传功
传动
传单
传去
传号
传名
传告
传呼
传唤
传唱
传回
传国
传声
传奇
传媒
传子
传宗
传审
传家
传对
传导
传布
传开
传得
传情
传感
传戒
传扬
传承
传抄
传报
传授
传播
传教
传旨
传本
传来
传染
传标
传毒
传热
传球
传电
传略
传看
传真
传着
传神
传票
传种
传粉
传经
传给
传统
传自
传艺
传观
传言
传讯
传记
传讹
传译
传话
传说
传诵
传谕
传谣
传质
传赞
传起
传输
传达
传过
传述
传送
传递
传遍
传道
传销
传问
传闻
传阅
传颂
传魂
伢子
伤了
伤亡
伤人
伤俘
伤兵
伤到
伤力
伤势
伤口
伤号
伤员
伤在
伤型
伤处
伤害
伤寒
伤得
伤心
伤怀
伤患
伤悲
伤悼
伤情
伤愈
伤感
伤损
伤残
伤气
伤生
伤疤
伤病
伤痕
伤痛
伤眼
伤着
伤神
伤科
伤者
伤耗
伤肺
伤肾
伤胃
伤财
伤身
伤过
伤透
伤逝
伤错
伤风
伥鬼
伦台
伦巴
伦常
伦敦
伦次
伦比
伦理
伦琴
伦纪
伦飞
伧俗
伧父
伪书
伪作
伪供
伪军
伪力
伪劣
伪名
伪命
伪品
伪善
伪学
伪币
伪彩
伪托
伪报
伪本
伪满
伪称
伪经
伪药
伪装
伪言
伪誓
伪证
伪谬
伪足
伪造
伪钞
伪饰
伫候
伫列
伫立
伫足
伯乐
伯仲
伯伯
伯克
伯公
伯利
伯劳
伯婆
伯尔
伯德
伯恩
伯斯
伯母
伯爵
伯父
伯牙
伯祖
估产
估价
估估
估分
估到
估单
估成
估摸
估测
估算
估衣
估计
估评
估量
伴你
伴侣
伴偶
伴儿
伴同
伴唱
伴奏
伴娘
伴我
伴星
伴有
伴游
伴生
伴舞
伴读
伴送
伴郎
伴随
伴靓
伴音
伴食
伶人
伶仃
伶俐
伶俜
伸上
伸下
伸伸
伸入
伸冤
伸出
伸到
伸去
伸及
伸向
伸回
伸在
伸头
伸屈
伸展
伸平
伸延
伸开
伸张
伸手
伸曲
伸来
伸港
伸畅
伸直
伸着
伸缩
伸脚
伸腰
伸腿
伸诉
伸起
伸过
伸进
伸长
伺侯
伺候
伺奉
伺察
伺服
伺机
伺隙
似乎
似可
似地
似旧
似是
似曾
似有
似水
似火
似的
似能
似角
似钢
似锦
伽师
伽蓝
佃农
佃妇
佃客
佃户
佃权
佃租
佃粮
但丁
但不
但也
但书
但亏
但从
但他
但会
但凡
但凭
但却
但又
但可
但因
但在
但她
但子
但它
但对
但应
但愿
但我
但无
但是
但有
但未
但求
但能
但要
但见
但须
但马
位于
位元
位列
位势
位图
位在
位址
位处
位子
位尊
位居
位差
位数
位标
位次
位相
位码
位移
位纤
位线
位置
位能
位色
低下
低买
低了
低于
低云
低产
低人
低价
低估
低位
低俗
低保
低做
低凹
低分
低利
低到
低劣
低压
低吟
低哑
低唱
低回
低地
低坝
低垂
低声
低处
低头
低层
低峰
低平
低年
低幼
低度
低廉
低徊
低得
低微
低息
低手
低效
低柔
低栏
低格
低档
低段
低毒
低氧
低沈
低沉
低洼
低浅
低温
低湿
低潮
低点
低烧
低热
低版
低相
低眉
低着
低矮
低穹
低空
低端
低等
低糖
低级
低缓
低耗
低胸
低能
低腰
低荡
低落
低薪
低语
低调
低谷
低贱
低迷
低速
低阶
低陷
低音
低频
低飞
低首
低龄
住上
住下
住个
住乐
住了
住到
住勤
住友
住口
住嘴
住在
住地
住址
住处
住外
住宅
住家
住宿
住寺
住居
住屋
住店
住得
住惯
住户
住房
住所
住手
住持
住有
住校
住民
住用
住留
住着
住者
住诊
住读
住起
住足
住进
住院
佐伯
佐使
佐剂
佐料
佐理
佐罗
佐藤
佐证
佐酒
佐野
佐餐
佑助
佑庇
佑德
佑护
体专
体会
体位
体例
体内
体制
体力
体协
体味
体坛
体型
体壁
体外
体委
体宽
体察
体尝
体己
体已
体式
体弱
体形
体彩
体征
体念
体态
体性
体总
体恤
体息
体悉
体悟
体惜
体操
体改
体查
体校
体格
体检
体法
体液
体温
体热
体现
体用
体癣
体积
体系
体统
体罚
体肤
体育
体能
体腔
体臭
体节
体范
体虱
体表
体裁
体要
体视
体觉
体认
体词
体谅
体貌
体质
体贴
体重
体量
体长
体院
体面
体香
体验
体高
体魄
何不
何为
何也
何事
何人
何以
何仪
何伟
何其
何冰
何况
何勇
何啻
何国
何在
何地
何堪
何处
何如
何妨
何尝
何干
何年
何当
何必
何患
何惧
何愁
何意
何故
何方
何日
何时
何晏
何晴
何曾
何月
何来
何样
何止
何洁
何燕
何物
何独
何琳
何用
何种
何等
何羲
何者
何能
何苗
何若
何苦
何解
何许
何谈
何谓
何足
何进
何队
何难
何雨
何需
何静
何音
何须
何麟
佘靖
余下
余事
余人
余值
余元
余光
余党
余兴
余切
余利
余剩
余割
余力
余味
余地
余址
余外
余天
余头
余姚
余威
余存
余孽
余家
余巾
余干
余年
余庆
余弦
余悸
余情
余数
余料
余日
余晖
余暇
余杭
余桃
余模
余款
余步
余毒
余氯
余江
余波
余泽
余温
余烬
余热
余犯
余生
余电
余留
余种
余粮
余缺
余者
余脉
余荫
余蓄
余裕
余角
余言
余辉
余量
余钱
余闲
余震
余音
余韵
余项
余额
余风
余香
佚事
佚名
佚失
佚文
佛事
佛佗
佛像
佛光
佛典
佛冈
佛力
佛协
佛号
佛国
佛土
佛坪
佛堂
佛塔
佛头
佛如
佛学
佛宝
佛家
佛寺
佛山
佛心
佛性
佛手
佛教
佛殿
佛法
佛湾
佛灯
佛爷
佛牙
佛珠
佛祖
佛经
佛老
佛诞
佛语
佛释
佛门
佛陀
佛青
佛骨
佛龛
作业
作东
作为
作主
作乐
作乱
作了
作事
作些
作人
作件
作价
作伐
作伥
作伪
作伴
作何
作俑
作保
作假
作兴
作准
作出
作别
作到
作功
作势
作协
作古
作呕
作和
作品
作响
作图
作坊
作声
作多
作好
作嫁
作孽
作宅
作官
作客
作家
作对
作崇
作工
作庄
作序
作废
作弄
作弊
作态
作怒
作怪
作息
作恶
作戏
作成
作战
作揖
作操
作数
作文
作料
作曲
作案
作梗
作梦
作槽
作歹
作死
作法
作活
作派
作爱
作物
作甚
作用
作画
作痛
作祟
作秀
作答
作罢
作美
作者
作脸
作船
作色
作艺
作证
作词
作诗
作账
作贱
作贼
作赔
作践
作过
作陪
作难
作风
作饭
作鬼
佝偻
佞人
佞佛
佞口
佞笑
佞臣
你们
你俩
你哥
你好
你妈
你家
你弟
你想
你我
你报
你爹
佣书
佣人
佣仆
佣兵
佣奴
佣工
佣懒
佣耕
佣金
佣钱
佤族
佩佩
佩兰
佩刀
佩剑
佩巾
佩带
佩思
佩恩
佩戴
佩挂
佩服
佩枪
佩特
佩玉
佩环
佩着
佩花
佩诺
佩迪
佩饰
佯伪
佯动
佯嗔
佯改
佯攻
佯死
佯狂
佯称
佯笑
佯细
佯装
佯言
佯谬
佯降
佳丽
佳人
佳作
佳佳
佳侣
佳偶
佳冬
佳利
佳县
佳句
佳品
佳园
佳城
佳境
佳妙
佳婿
佳客
佳宾
佳日
佳旺
佳景
佳期
佳构
佳篇
佳约
佳绩
佳美
佳肴
佳能
佳节
佳茗
佳讯
佳评
佳话
佳貌
佳软
佳运
佳酝
佳酿
佳里
佳闻
佳音
佻巧
佻薄
佻达
佼佼
佼容
佼貌
佾生
佾舞
使令
使其
使出
使劲
使君
使命
使唤
使团
使坏
使坐
使女
使役
使徒
使得
使然
使用
使者
使臣
使舵
使节
使馆
侃侃
侃山
侃快
侃直
侄儿
侄女
侄妇
侄婿
侄媳
侄子
侄孙
侈言
侈谈
侈靡
侉子
例举
例会
例假
例句
例外
例如
例子
例数
例文
例案
例牌
例示
例程
例行
例规
例言
例证
例语
例题
侍中
侍仆
侍从
侍侯
侍候
侍养
侍剑
侍卫
侍奉
侍女
侍妾
侍应
侍弄
侍立
侍童
侍者
侍郎
侍魂
侏儒
侗乡
侗寨
侗族
供事
供人
供住
供体
供佛
供养
供出
供制
供办
供品
供售
供在
供堂
供奉
供应
供房
供招
供料
供暖
供果
供案
供桌
供楼
供气
供水
供求
供油
供热
供状
供电
供神
供种
供称
供稿
供粮
供给
供职
供认
供词
供说
供货
供述
供销
供需
供餐
依人
依从
依仗
依例
依侍
依依
依偎
依傍
依允
依兰
依其
依凭
依存
依安
依序
依归
依律
依循
依恋
依我
依托
依据
依旧
依星
依杖
依样
依次
依此
依法
依滢
依然
依照
依物
依率
依稀
依约
依纪
依赖
依通
依附
依随
依靠
依顺
侠义
侠侣
侠士
侠女
侠客
侠心
侠气
侠溪
侠白
侠盗
侠行
侠辣
侠风
侠骨
侣伴
侥幸
侦候
侦办
侦听
侦察
侦探
侦控
侦查
侦检
侦毒
侦测
侦破
侦结
侦缉
侦获
侦讯
侦问
侦防
侦骑
侧冲
侧击
侧刀
侧卧
侧厅
侧台
侧后
侧向
侧堡
侧壁
侧室
侧影
侧方
侧旁
侧枝
侧柏
侧柱
侧根
侧泳
侧目
侧睡
侧笔
侧线
侧翼
侧耳
侧腹
侧芽
侧视
侧记
侧身
侧边
侧近
侧部
侧重
侧门
侧闻
侧面
侨乡
侨办
侨务
侨商
侨团
侨居
侨属
侨情
侨报
侨校
侨民
侨汇
侨生
侨界
侨眷
侨社
侨联
侨胞
侨资
侨陵
侨领
侪辈
侮弄
侮慢
侮蔑
侮辱
侮骂
侯勇
侯国
侯府
侯方
侯爵
侯爷
侯补
侯车
侯选
侯门
侯马
侯鸟
侵伐
侵入
侵凌
侵华
侵占
侵吞
侵夺
侵害
侵并
侵扰
侵晓
侵晨
侵权
侵染
侵犯
侵略
侵蚀
侵袭
侵越
便中
便了
便于
便会
便函
便利
便去
便可
便名
便在
便士
便壶
便学
便宜
便宴
便尿
便帽
便应
便当
便所
便打
便把
便捷
便携
便是
便有
便服
便条
便桥
便桶
便步
便民
便池
便溺
便盆
便知
便秘
便笺
便签
便给
便能
便药
便菜
便血
便衣
便装
便要
便览
便路
便车
便辟
便道
便酌
便门
便鞋
便餐
便饭
促产
促使
促动
促成
促狭
促脉
促膝
促请
促进
促退
促销
俄人
俄共
俄军
俄国
俄城
俄帝
俄式
俄文
俄方
俄皇
俄而
俄语
俄顷
俊伟
俊俏
俊儿
俊彦
俊朗
俊材
俊杰
俊爽
俊男
俊秀
俊美
俊逸
俊雅
俊马
俏丽
俏似
俏俏
俏唇
俏头
俏女
俏皮
俏货
俏销
俏鬼
俐落
俑坑
俗业
俗乐
俗事
俗人
俗体
俗例
俗务
俗化
俗名
俗士
俗套
俗子
俗字
俗学
俗家
俗尚
俗念
俗态
俗曲
俗气
俗物
俗琐
俗称
俗缘
俗艳
俗论
俗话
俗语
俗谚
俗谛
俘敌
俘获
俘虏
俚俗
俚医
俚曲
俚歌
俚言
俚语
俚谚
保举
保久
保产
保人
保价
保住
保佑
保供
保修
保值
保健
保全
保养
保准
保利
保单
保卫
保命
保固
保土
保墒
保外
保姆
保婴
保媒
保存
保守
保安
保定
保家
保密
保尔
保山
保底
保康
保德
保息
保护
保持
保暖
保有
保本
保正
保民
保洁
保温
保湿
保溼
保状
保用
保甲
保留
保皇
保真
保票
保秘
保税
保管
保级
保结
保罗
保育
保胎
保苗
保荐
保藏
保警
保证
保质
保费
保赦
保身
保送
保释
保重
保量
保金
保钓
保镖
保长
保防
保险
保障
保靖
保驾
保鲜
俞允
俞府
俞穴
俞静
俟机
信上
信个
信中
信丰
信义
信从
信仰
信件
信任
信佛
信使
信内
信函
信到
信包
信区
信口
信史
信号
信增
信士
信奉
信女
信守
信宜
信实
信封
信差
信度
信徒
信得
信徙
信德
信心
信念
信息
信我
信手
信托
信据
信教
信文
信服
信望
信札
信条
信标
信步
信汇
信江
信源
信物
信用
信皮
信石
信社
信稿
信笔
信笺
信筒
信简
信管
信箱
信纸
信耐
信誉
信访
信诊
信贷
信赏
信赖
信达
信道
信邪
信里
信长
信阳
信风
信鸟
信鸽
俨如
俨然
俨若
俩人
俩月
俩眼
俪人
俪句
俪影
俪辞
俭岁
俭明
俭朴
俭汤
俭用
俭省
俭约
修业
修习
修书
修仙
修修
修养
修函
修到
修剪
修史
修堤
修士
修复
修女
修好
修学
修定
修己
修庆
修建
修得
修憩
修成
修房
修护
修持
修撰
修改
修整
修文
修明
修枝
修桥
修正
修武
修水
修治
修浚
修炼
修理
修短
修竹
修筑
修纂
修编
修缮
修罗
修脚
修脸
修船
修葺
修行
修补
修订
修读
修课
修起
修路
修蹄
修身
修车
修辞
修造
修道
修配
修长
修面
修鞋
修饰
修齐
俯下
俯仰
俯伏
俯允
俯冲
俯卧
俯头
俯姿
俯察
俯射
俯就
俯念
俯拍
俯拾
俯曲
俯泳
俯看
俯瞰
俯视
俯角
俯贻
俯身
俯首
俱佳
俱全
俱发
俱在
俱备
俱往
俳优
俳句
俳谐
俸恤
俸禄
俸给
俸褖
俸钱
俺们
俺家
俺村
俾使
俾倪
俾能
俾面
倍于
倍偿
倍儿
倍加
倍受
倍增
倍律
倍感
倍数
倍特
倍率
倍生
倍称
倍觉
倍谢
倍速
倍频
倏地
倏尔
倏忽
倏然
倒上
倒下
倒为
倒也
倒买
倒了
倒仓
倒伏
倒休
倒会
倒倒
倒像
倒入
倒八
倒写
倒出
倒到
倒刺
倒剪
倒包
倒卖
倒卧
倒去
倒反
倒叙
倒句
倒台
倒吃
倒向
倒吸
倒嗓
倒嚼
倒回
倒在
倒地
倒坍
倒垂
倒塌
倒头
倒好
倒帐
倒带
倒床
倒彩
倒影
倒得
倒念
倒悬
倒想
倒戈
倒手
倒扣
倒找
倒把
倒折
倒拉
倒挂
倒换
倒掉
倒排
倒推
倒插
倒放
倒数
倒料
倒映
倒是
倒替
倒来
倒杯
倒楣
倒毁
倒毙
倒水
倒汇
倒油
倒流
倒满
倒灌
倒灶
倒焊
倒爷
倒班
倒睫
倒票
倒空
倒立
倒算
倒粪
倒给
倒置
倒翁
倒胃
倒背
倒腾
倒茬
倒茶
倒萨
倒行
倒装
倒要
倒角
倒计
倒账
倒贴
倒赔
倒走
倒起
倒车
倒转
倒过
倒运
倒还
倒进
倒退
倒锁
倒错
倒闭
倒阁
倒霉
倔劲
倔强
倔犟
倘不
倘佯
倘使
倘或
倘有
倘未
倘然
倘能
倘若
候光
候命
候场
候复
候审
候教
候机
候温
候爵
候缺
候船
候补
候诊
候车
候选
候销
候马
候驾
候鱼
候鸟
倚仗
倚偎
倚傍
倚坐
倚天
倚恃
倚望
倚栏
倚立
倚赖
倚重
倚门
倚靠
倚音
倜傥
借个
借书
借了
借人
借代
借以
借位
借住
借余
借作
借你
借借
借债
借光
借入
借兵
借减
借出
借到
借助
借势
借去
借取
借口
借唱
借喻
借回
借地
借坐
借垫
借增
借好
借完
借宿
借差
借帐
借弹
借得
借我
借托
借抄
借抽
借招
借据
借支
借放
借故
借方
借有
借期
借机
借条
借来
借款
借此
借满
借火
借点
借球
借用
借看
借着
借穿
借端
借约
借给
借自
借让
借词
借读
借调
借账
借贷
借走
借车
借过
借还
借道
借酒
借重
借鉴
借钱
借镜
借问
借阅
借领
借题
倡乱
倡仪
倡优
倡导
倡廉
倡狂
倡言
倡议
倡首
倥侗
倦乏
倦勤
倦容
倦态
倦怠
倦意
倦感
倦游
倦色
倨傲
倩倩
倩况
倩女
倩影
倪匡
倪平
倪浩
倪萍
倭奴
倭寇
倭瓜
债主
债利
债券
债务
债台
债市
债息
债户
债权
债款
债额
值了
值勤
值参
值域
值夜
值守
值完
值当
值得
值日
值星
值更
值此
值班
值遇
值钱
倾下
倾于
倾侧
倾倒
倾入
倾出
倾刻
倾力
倾动
倾化
倾危
倾卸
倾吐
倾向
倾听
倾囊
倾国
倾城
倾塌
倾复
倾天
倾宵
倾家
倾巢
倾度
倾心
倾情
倾慕
倾斜
倾析
倾泄
倾注
倾泻
倾盆
倾盖
倾羡
倾耳
倾船
倾覆
倾角
倾诉
倾谈
倾轧
倾销
倾陷
倾颓
偃卧
偃师
偃月
偃松
假人
假令
假传
假作
假使
假借
假充
假冒
假列
假劣
假单
假发
假名
假哭
假图
假如
假娘
假孕
假定
假寐
假山
假峰
假币
假带
假座
假得
假性
假惜
假想
假意
假手
假托
假扮
假报
假摔
假日
假期
假条
假果
假根
假案
假植
假死
假泪
假牌
假牙
假球
假用
假画
假皮
假相
假眼
假睡
假票
假种
假笑
假结
假缎
假肢
假色
假若
假药
假装
假言
假设
假证
假话
假说
假象
假账
假货
假贷
假足
假送
假造
假道
假酒
假释
假钞
假钱
假锁
假门
假面
假领
假髻
假鱼
假齿
偌大
偎依
偎倚
偎傍
偎抱
偎着
偎贴
偎近
偏上
偏下
偏不
偏东
偏了
偏于
偏会
偏低
偏信
偏倒
偏倚
偏偏
偏僻
偏光
偏关
偏到
偏劳
偏北
偏南
偏历
偏压
偏去
偏右
偏后
偏向
偏听
偏回
偏在
偏处
偏外
偏多
偏大
偏失
偏头
偏好
偏守
偏安
偏宜
偏室
偏宽
偏射
偏将
偏小
偏少
偏峰
偏左
偏巧
偏差
偏己
偏巷
偏店
偏废
偏得
偏德
偏心
偏房
偏执
偏护
偏振
偏掉
偏斜
偏方
偏旁
偏是
偏暗
偏有
偏来
偏松
偏析
偏枯
偏正
偏歪
偏殿
偏流
偏激
偏爱
偏狂
偏狭
偏疼
偏瘦
偏瘫
偏着
偏短
偏码
偏离
偏私
偏科
偏移
偏窄
偏紧
偏紫
偏累
偏细
偏置
偏胖
偏至
偏航
偏色
偏蓝
偏蚀
偏衫
偏袒
偏西
偏要
偏见
偏角
偏转
偏轻
偏辞
偏远
偏重
偏锋
偏长
偏门
偏靠
偏顾
偏颇
偏题
偏食
偏饭
偏高
偏黄
偕同
偕老
偕行
做上
做东
做个
做为
做主
做了
做事
做些
做亲
做人
做伴
做作
做你
做保
做假
做做
做出
做到
做功
做台
做呕
做回
做在
做声
做大
做好
做媒
做完
做官
做客
做对
做寿
做小
做工
做庄
做得
做戏
做成
做手
做掉
做操
做案
做梦
做比
做法
做活
做派
做爱
做牌
做的
做着
做秀
做种
做答
做给
做脸
做菜
做表
做诗
做账
做贼
做起
做过
做错
做题
做饭
做鬼
停上
停下
停业
停了
停产
停付
停会
停住
停停
停刊
停到
停制
停办
停匀
停发
停售
停在
停好
停妥
停学
停完
停尸
停工
停建
停开
停当
停征
停得
停徵
停息
停战
停手
停拨
停掉
停摆
停播
停放
停显
停有
停机
停板
停歇
停止
停步
停水
停泊
停滞
停火
停灵
停用
停电
停留
停着
停站
停笔
停约
停线
停经
停缴
停置
停职
停航
停船
停药
停薪
停表
停训
停诊
停话
停课
停赛
停蹄
停车
停转
停载
停过
停进
停错
停闭
停靠
停顿
停飞
停食
停驶
停驻
健体
健儿
健全
健在
健壮
健存
健将
健康
健忘
健教
健旺
健朗
健步
健民
健硕
健立
健美
健胃
健脑
健脾
健行
健谈
健身
偶一
偶人
偶们
偶像
偶发
偶合
偶姻
偶尔
偶性
偶感
偶或
偶提
偶数
偶有
偶氮
偶然
偶犯
偶笔
偶而
偶联
偶见
偶记
偶语
偶象
偶起
偶逢
偶遇
偷上
偷下
偷书
偷了
偷人
偷作
偷做
偷停
偷偷
偷光
偷入
偷凉
偷出
偷到
偷办
偷加
偷包
偷去
偷发
偷取
偷叫
偷吃
偷听
偷吸
偷售
偷喝
偷嘴
偷回
偷垒
偷填
偷夹
偷存
偷学
偷安
偷宰
偷寄
偷工
偷巧
偷师
偷带
偷开
偷录
偷得
偷心
偷情
偷懒
偷打
偷抄
偷报
偷抱
偷拍
偷拿
偷换
偷搞
偷搬
偷摸
偷收
偷教
偷数
偷来
偷架
偷欢
偷水
偷油
偷法
偷泡
偷洗
偷渡
偷溜
偷漏
偷炒
偷猎
偷球
偷生
偷电
偷盗
偷看
偷眼
偷着
偷睡
偷砍
偷种
偷税
偷空
偷窃
偷窥
偷笑
偷腥
偷花
偷营
偷袭
偷讲
偷请
偷读
偷课
偷调
偷走
偷起
偷越
偷跑
偷跳
偷车
偷载
偷过
偷运
偷逃
偷采
偷钱
偷铁
偷闲
偷领
偷骑
偺们
偿付
偿债
偿命
偿回
偿愿
偿清
偿还
傀儡
傀奇
傀异
傀标
傅体
傅园
傅娟
傅彩
傅彪
傅斌
傅杰
傅粉
傈僳
傍偟
傍午
傍徨
傍晚
傍水
傍系
傍边
傍靠
傍黑
傢俬
傣乡
傣历
傣味
傣族
傧相
储位
储供
储君
储备
储存
储户
储放
储水
储油
储波
储积
储粮
储罐
储蓄
储藏
储装
储训
储贷
储运
储量
储金
傩神
催产
催促
催债
催健
催办
催化
催发
催吐
催告
催命
催奶
催征
催情
催收
催林
催款
催残
催毁
催泪
催熟
催片
催生
催眠
催租
催粮
催缴
催肥
催芽
催讨
催赶
催还
催逼
催青
傲世
傲人
傲剑
傲岸
傲性
傲慢
傲气
傲然
傲物
傲视
傲骨
傻乐
傻了
傻事
傻人
傻傻
傻冒
傻劲
傻女
傻子
傻屄
傻帽
傻干
傻强
傻憨
傻气
傻狗
傻瓜
傻眼
傻笑
傻等
傻脱
傻蛋
傻话
傻高
僇辱
像个
像他
像似
像你
像册
像前
像图
像圈
像在
像她
像差
像您
像我
像是
像样
像片
像章
像素
像胶
像被
像要
像话
像貌
像距
僚佐
僚友
僚属
僚机
僧人
僧众
僧伽
僧侣
僧俗
僧堂
僧孺
僧寺
僧尼
僧帽
僧徒
僧服
僧肇
僧衣
僧袍
僧院
僧面
僧鞋
僭取
僭号
僭越
僮仆
僵住
僵冷
僵冻
僵化
僵卧
僵固
僵尸
僵局
僵持
僵掉
僵死
僵滞
僵直
僵硬
僵立
僵蚕
僻典
僻壤
僻字
僻巷
僻远
僻道
僻陋
僻静
儋县
儋州
儒医
儒商
儒墨
儒士
儒学
儒家
儒将
儒教
儒术
儒林
儒生
儒者
儒艮
儒道
儒雅
儿化
儿女
儿媳
儿子
儿孙
儿少
儿戏
儿时
儿歌
儿男
儿科
儿童
儿茶
儿郎
儿马
兀傲
兀然
兀突
兀立
兀自
兀鹫
兀鹰
允从
允准
允可
允当
允承
允武
允许
允诺
元人
元代
元件
元任
元伤
元元
元兄
元凳
元凶
元初
元功
元勋
元华
元古
元史
元嘉
元培
元夜
元女
元始
元子
元宝
元宵
元山
元帅
元帝
元年
元彪
元彬
元恶
元悲
元戎
元斌
元日
元旦
元明
元曲
元月
元朔
元朗
元朝
元本
元柳
元桌
元氏
元气
元江
元煤
元狩
元由
元痛
元祖
元稹
元素
元组
元老
元臣
元色
元谋
元配
元针
元钉
元门
元阳
元雅
元霄
元音
元首
元鱼
元麦
兄台
兄妹
兄姐
兄嫂
兄弟
兄贵
兄长
充任
充仿
充作
充值
充假
充充
充公
充军
充分
充到
充塞
充填
充好
充实
充当
充数
充斥
充气
充水
充沛
充溢
充满
充电
充畅
充盈
充盛
充磁
充腹
充血
充裕
充要
充足
充阔
充饥
兆位
兆周
兆头
兆惠
兆欧
兆瓦
兆示
兆赫
先上
先下
先世
先严
先为
先了
先予
先于
先交
先人
先从
先付
先令
先以
先会
先住
先例
先倒
先借
先兄
先兆
先公
先写
先决
先减
先出
先刊
先列
先别
先到
先前
先剪
先包
先占
先去
先发
先取
先吃
先同
先后
先向
先君
先听
先吸
先哭
先哲
先唱
先喝
先嚐
先回
先圣
先在
先声
先天
先夫
先头
先套
先妣
先存
先守
先宰
先容
先寄
先富
先导
先将
先尝
先就
先师
先帝
先带
先应
先延
先开
先往
先征
先得
先想
先慈
先战
先戴
gitextract_7eqaxw1n/
├── .github/
│ └── ISSUE_TEMPLATE/
│ └── bug_report.md
├── .gitignore
├── .travis.yml
├── CONTRIBUTING.md
├── LICENSE
├── README-CLOUD.md
├── README.md
├── pom.xml
└── src/
└── main/
├── java/
│ └── org/
│ └── wltea/
│ └── analyzer/
│ ├── cfg/
│ │ ├── Configuration.java
│ │ └── DefaultConfig.java
│ ├── core/
│ │ ├── AnalyzeContext.java
│ │ ├── CJKSegmenter.java
│ │ ├── CN_QuantifierSegmenter.java
│ │ ├── CharacterUtil.java
│ │ ├── IKArbitrator.java
│ │ ├── IKSegmenter.java
│ │ ├── ISegmenter.java
│ │ ├── LetterSegmenter.java
│ │ ├── Lexeme.java
│ │ ├── LexemePath.java
│ │ └── QuickSortSet.java
│ ├── dic/
│ │ ├── DictSegment.java
│ │ ├── Dictionary.java
│ │ └── Hit.java
│ ├── lucene/
│ │ ├── IKAnalyzer.java
│ │ ├── IKTokenizer.java
│ │ ├── IKTokenizerFactory.java
│ │ └── UpdateThread.java
│ └── query/
│ ├── IKQueryExpressionParser.java
│ └── SWMCQueryBuilder.java
└── resources/
├── IKAnalyzer.cfg.xml
├── dict/
│ ├── main2012.dic
│ ├── main_dic_2020.dic
│ └── quantifier.dic
├── dynamicdic.txt
├── ext.dic
├── ik.conf
└── stopword.dic
SYMBOL INDEX (229 symbols across 22 files)
FILE: src/main/java/org/wltea/analyzer/cfg/Configuration.java
type Configuration (line 35) | public interface Configuration {
method useSmart (line 44) | boolean useSmart();
method setUseSmart (line 51) | void setUseSmart(boolean useSmart);
method useMainDict (line 58) | boolean useMainDict();
method setUseMainDict (line 65) | void setUseMainDict(boolean useMainDic);
method getMainDictionary (line 72) | String getMainDictionary();
method getQuantifierDictionary (line 79) | String getQuantifierDictionary();
method getExtDictionarys (line 86) | List<String> getExtDictionarys();
method getExtStopWordDictionarys (line 94) | List<String> getExtStopWordDictionarys();
FILE: src/main/java/org/wltea/analyzer/cfg/DefaultConfig.java
class DefaultConfig (line 39) | public class DefaultConfig implements Configuration {
method getInstance (line 71) | public static Configuration getInstance() {
method DefaultConfig (line 78) | private DefaultConfig() {
method useSmart (line 98) | public boolean useSmart() {
method setUseSmart (line 107) | @Override
method useMainDict (line 117) | public boolean useMainDict() {
method setUseMainDict (line 129) | @Override
method getMainDictionary (line 139) | public String getMainDictionary() {
method getQuantifierDictionary (line 148) | public String getQuantifierDictionary() {
method getExtDictionarys (line 157) | public List<String> getExtDictionarys() {
method getExtStopWordDictionarys (line 177) | public List<String> getExtStopWordDictionarys() {
FILE: src/main/java/org/wltea/analyzer/core/AnalyzeContext.java
class AnalyzeContext (line 40) | class AnalyzeContext {
method AnalyzeContext (line 77) | AnalyzeContext(Configuration cfg) {
method getCursor (line 87) | int getCursor() {
method getSegmentBuff (line 91) | char[] getSegmentBuff() {
method getCurrentChar (line 95) | char getCurrentChar() {
method getCurrentCharType (line 99) | int getCurrentCharType() {
method getBufferOffset (line 103) | int getBufferOffset() {
method fillBuffer (line 113) | int fillBuffer(Reader reader) throws IOException {
method initCursor (line 138) | void initCursor() {
method moveCursor (line 149) | boolean moveCursor() {
method lockBuffer (line 164) | void lockBuffer(String segmenterName) {
method unlockBuffer (line 171) | void unlockBuffer(String segmenterName) {
method isBufferLocked (line 181) | private boolean isBufferLocked() {
method isBufferConsumed (line 189) | boolean isBufferConsumed() {
method needRefillBuffer (line 202) | boolean needRefillBuffer() {
method markBufferOffset (line 212) | void markBufferOffset() {
method addLexeme (line 221) | void addLexeme(Lexeme lexeme) {
method addLexemePath (line 231) | void addLexemePath(LexemePath path) {
method getOrgLexemes (line 241) | QuickSortSet getOrgLexemes() {
method outputToResult (line 251) | void outputToResult() {
method outputSingleCJK (line 291) | private void outputSingleCJK(int index) {
method getNextLexeme (line 306) | Lexeme getNextLexeme() {
method reset (line 327) | void reset() {
method compound (line 342) | private void compound(Lexeme result) {
FILE: src/main/java/org/wltea/analyzer/core/CJKSegmenter.java
class CJKSegmenter (line 40) | class CJKSegmenter implements ISegmenter {
method CJKSegmenter (line 48) | CJKSegmenter() {
method analyze (line 55) | public void analyze(AnalyzeContext context) {
method reset (line 122) | public void reset() {
FILE: src/main/java/org/wltea/analyzer/core/CN_QuantifierSegmenter.java
class CN_QuantifierSegmenter (line 41) | class CN_QuantifierSegmenter implements ISegmenter {
method CN_QuantifierSegmenter (line 73) | CN_QuantifierSegmenter() {
method analyze (line 82) | public void analyze(AnalyzeContext context) {
method reset (line 101) | public void reset() {
method processCNumber (line 110) | private void processCNumber(AnalyzeContext context) {
method processCount (line 149) | private void processCount(AnalyzeContext context) {
method needCountScan (line 212) | private boolean needCountScan(AnalyzeContext context) {
method outputNumLexeme (line 233) | private void outputNumLexeme(AnalyzeContext context) {
FILE: src/main/java/org/wltea/analyzer/core/CharacterUtil.java
class CharacterUtil (line 33) | class CharacterUtil {
method identifyCharType (line 52) | static int identifyCharType(char input) {
method regularize (line 92) | static char regularize(char input) {
FILE: src/main/java/org/wltea/analyzer/core/IKArbitrator.java
class IKArbitrator (line 36) | class IKArbitrator {
method IKArbitrator (line 38) | IKArbitrator() {}
method process (line 46) | void process(AnalyzeContext context, boolean useSmart) {
method judge (line 93) | private LexemePath judge(QuickSortSet.Cell lexemeCell) {
method forwardPath (line 124) | private Stack<QuickSortSet.Cell> forwardPath(QuickSortSet.Cell lexemeC...
method backPath (line 142) | private void backPath(Lexeme l, LexemePath option) {
FILE: src/main/java/org/wltea/analyzer/core/IKSegmenter.java
class IKSegmenter (line 42) | public final class IKSegmenter {
method IKSegmenter (line 74) | public IKSegmenter(Reader input, boolean useSmart) {
method IKSegmenter (line 87) | @SuppressWarnings("unused")
method init (line 97) | private void init() {
method loadSegmenters (line 113) | private List<ISegmenter> loadSegmenters() {
method next (line 129) | public synchronized Lexeme next() throws IOException {
method reset (line 177) | public synchronized void reset(Reader input) {
FILE: src/main/java/org/wltea/analyzer/core/ISegmenter.java
type ISegmenter (line 34) | interface ISegmenter {
method analyze (line 41) | void analyze(AnalyzeContext context);
method reset (line 47) | void reset();
FILE: src/main/java/org/wltea/analyzer/core/LetterSegmenter.java
class LetterSegmenter (line 35) | class LetterSegmenter implements ISegmenter {
method LetterSegmenter (line 77) | LetterSegmenter() {
method analyze (line 92) | public void analyze(AnalyzeContext context) {
method reset (line 113) | public void reset() {
method processMixLetter (line 128) | private boolean processMixLetter(AnalyzeContext context) {
method processEnglishLetter (line 179) | private boolean processEnglishLetter(AnalyzeContext context) {
method processArabicLetter (line 222) | private boolean processArabicLetter(AnalyzeContext context) {
method isLetterConnector (line 268) | private boolean isLetterConnector(char input) {
method isNumConnector (line 278) | @SuppressWarnings("unused")
FILE: src/main/java/org/wltea/analyzer/core/Lexeme.java
class Lexeme (line 33) | @SuppressWarnings("unused")
method Lexeme (line 93) | public Lexeme(int offset, int begin, int length, int lexemeType) {
method equals (line 108) | public boolean equals(Object o) {
method hashCode (line 131) | public int hashCode() {
method compareTo (line 141) | public int compareTo(Lexeme other) {
method getOffset (line 155) | private int getOffset() {
method setOffset (line 159) | public void setOffset(int offset) {
method getBegin (line 163) | int getBegin() {
method getBeginPosition (line 172) | public int getBeginPosition() {
method setBegin (line 176) | public void setBegin(int begin) {
method getEndPosition (line 185) | public int getEndPosition() {
method getLength (line 194) | public int getLength() {
method setLength (line 198) | public void setLength(int length) {
method getLexemeText (line 210) | public String getLexemeText() {
method setLexemeText (line 217) | void setLexemeText(String lexemeText) {
method getLexemeType (line 232) | int getLexemeType() {
method getLexemeTypeString (line 241) | public String getLexemeTypeString() {
method setLexemeType (line 277) | public void setLexemeType(int lexemeType) {
method append (line 286) | boolean append(Lexeme l, int lexemeType) {
method toString (line 301) | public String toString() {
FILE: src/main/java/org/wltea/analyzer/core/LexemePath.java
class LexemePath (line 34) | @SuppressWarnings("unused")
method LexemePath (line 50) | LexemePath() {
method addCrossLexeme (line 59) | boolean addCrossLexeme(Lexeme lexeme) {
method addNotCrossLexeme (line 84) | boolean addNotCrossLexeme(Lexeme lexeme) {
method removeTail (line 110) | void removeTail() {
method checkCross (line 126) | boolean checkCross(Lexeme lexeme) {
method getPathBegin (line 131) | int getPathBegin() {
method getPathEnd (line 135) | int getPathEnd() {
method getPayloadLength (line 142) | int getPayloadLength() {
method getPathLength (line 149) | private int getPathLength() {
method getXWeight (line 157) | private int getXWeight() {
method getPWeight (line 170) | private int getPWeight() {
method copy (line 182) | LexemePath copy() {
method compareTo (line 195) | public int compareTo(LexemePath o) {
method toString (line 241) | public String toString() {
FILE: src/main/java/org/wltea/analyzer/core/QuickSortSet.java
class QuickSortSet (line 33) | class QuickSortSet {
method QuickSortSet (line 47) | QuickSortSet() {
method addLexeme (line 54) | void addLexeme(Lexeme lexeme) {
method peekFirst (line 98) | Lexeme peekFirst() {
method pollFirst (line 110) | Lexeme pollFirst() {
method peekLast (line 130) | Lexeme peekLast() {
method pollLast (line 142) | Lexeme pollLast() {
method size (line 164) | int size() {
method isEmpty (line 171) | boolean isEmpty() {
method getHead (line 178) | Cell getHead() {
class Cell (line 187) | @SuppressWarnings("unused")
method Cell (line 193) | Cell(Lexeme lexeme) {
method compareTo (line 200) | public int compareTo(Cell o) {
method getPrev (line 204) | public Cell getPrev() {
method getNext (line 208) | Cell getNext() {
method getLexeme (line 212) | public Lexeme getLexeme() {
FILE: src/main/java/org/wltea/analyzer/dic/DictSegment.java
class DictSegment (line 37) | @SuppressWarnings("unused")
method DictSegment (line 75) | DictSegment(Character nodeChar) {
method getNodeChar (line 82) | Character getNodeChar() {
method hasNextNode (line 89) | private boolean hasNextNode() {
method match (line 98) | Hit match(char[] charArray) {
method match (line 107) | Hit match(char[] charArray, int begin, int length) {
method match (line 116) | Hit match(char[] charArray, int begin, int length, Hit searchHit) {
method fillSegment (line 180) | void fillSegment(char[] charArray) {
method disableSegment (line 187) | void disableSegment(char[] charArray) {
method fillSegment (line 194) | private synchronized void fillSegment(char[] charArray, int begin, int...
method lookforSegment (line 225) | private DictSegment lookforSegment(Character keyChar, int create) {
method getChildrenArray (line 287) | private DictSegment[] getChildrenArray() {
method getChildrenMap (line 302) | private Map<Character, DictSegment> getChildrenMap() {
method migrate (line 316) | private void migrate(DictSegment[] segmentArray, Map<Character, DictSe...
method compareTo (line 329) | public int compareTo(DictSegment o) {
FILE: src/main/java/org/wltea/analyzer/dic/Dictionary.java
class Dictionary (line 41) | @SuppressWarnings("unused")
method Dictionary (line 73) | private Dictionary(Configuration cfg) {
method initial (line 87) | public static void initial(Configuration cfg) {
method getSingleton (line 102) | public static Dictionary getSingleton() {
method reloadDic (line 115) | public static void reloadDic(List<Reader> inputStreamReaderList) {
method addWords (line 150) | public void addWords(Collection<String> words) {
method disableWords (line 164) | public void disableWords(Collection<String> words) {
method matchInMainDict (line 180) | public Hit matchInMainDict(char[] charArray) {
method matchInMainDict (line 189) | public Hit matchInMainDict(char[] charArray, int begin, int length) {
method matchInQuantifierDict (line 198) | public Hit matchInQuantifierDict(char[] charArray, int begin, int leng...
method matchWithHit (line 208) | public Hit matchWithHit(char[] charArray, int currentIndex, Hit matche...
method isStopWord (line 219) | public boolean isStopWord(char[] charArray, int begin, int length) {
method loadMainDict (line 226) | private void loadMainDict() {
method loadExtDict (line 257) | private void loadExtDict() {
method loadStopWordDict (line 290) | private void loadStopWordDict() {
method loadQuantifierDict (line 325) | private void loadQuantifierDict() {
method readDict (line 355) | private void readDict(InputStream is, DictSegment dictSegment) throws ...
FILE: src/main/java/org/wltea/analyzer/dic/Hit.java
class Hit (line 33) | @SuppressWarnings("unused")
method isMatch (line 70) | public boolean isMatch() {
method setMatch (line 76) | void setMatch() {
method isPrefix (line 83) | public boolean isPrefix() {
method setPrefix (line 89) | void setPrefix() {
method isUnmatch (line 95) | public boolean isUnmatch() {
method setUnmatch (line 99) | void setUnmatch() {
method getMatchedDictSegment (line 103) | DictSegment getMatchedDictSegment() {
method setMatchedDictSegment (line 107) | void setMatchedDictSegment(DictSegment matchedDictSegment) {
method getBegin (line 111) | public int getBegin() {
method setBegin (line 115) | void setBegin(int begin) {
method getEnd (line 119) | public int getEnd() {
method setEnd (line 123) | void setEnd(int end) {
FILE: src/main/java/org/wltea/analyzer/lucene/IKAnalyzer.java
class IKAnalyzer (line 36) | @SuppressWarnings("unused")
method useSmart (line 41) | private boolean useSmart() {
method IKAnalyzer (line 50) | public IKAnalyzer() {
method IKAnalyzer (line 59) | public IKAnalyzer(boolean useSmart) {
method createComponents (line 67) | @Override
FILE: src/main/java/org/wltea/analyzer/lucene/IKTokenizer.java
class IKTokenizer (line 43) | @SuppressWarnings({"unused", "FinalMethodInFinalClass"})
method IKTokenizer (line 71) | public IKTokenizer() {
method IKTokenizer (line 75) | IKTokenizer(boolean useSmart) {
method IKTokenizer (line 80) | public IKTokenizer(AttributeFactory factory) {
method IKTokenizer (line 84) | IKTokenizer(AttributeFactory factory, boolean useSmart) {
method init (line 89) | private void init(boolean useSmart) {
method incrementToken (line 100) | @Override
method reset (line 128) | @Override
method end (line 134) | @Override
FILE: src/main/java/org/wltea/analyzer/lucene/IKTokenizerFactory.java
class IKTokenizerFactory (line 51) | public class IKTokenizerFactory extends TokenizerFactory implements Reso...
method IKTokenizerFactory (line 57) | public IKTokenizerFactory(Map<String, String> args) {
method create (line 65) | @Override
method inform (line 77) | @Override
method update (line 92) | @Override
method canUpdate (line 121) | private Properties canUpdate() {
method SplitFileNames (line 154) | private static List<String> SplitFileNames(String fileNames) {
method useSmart (line 164) | private boolean useSmart() {
method setUseSmart (line 168) | private void setUseSmart(boolean useSmart) {
method getConf (line 172) | private String getConf() {
method setConf (line 176) | private void setConf(String conf) {
FILE: src/main/java/org/wltea/analyzer/lucene/UpdateThread.java
class UpdateThread (line 36) | public class UpdateThread implements Runnable {
method UpdateThread (line 43) | private UpdateThread() {
class Builder (line 53) | private static class Builder {
method getInstance (line 63) | static UpdateThread getInstance() {
method register (line 72) | void register(UpdateJob filterFactory) {
method run (line 79) | @Override
type UpdateJob (line 104) | public interface UpdateJob {
method update (line 105) | void update() throws IOException;
FILE: src/main/java/org/wltea/analyzer/query/IKQueryExpressionParser.java
class IKQueryExpressionParser (line 46) | public class IKQueryExpressionParser {
method parseExp (line 60) | private Query parseExp(String expression) {
method splitElements (line 85) | private void splitElements(String expression) {
method parseSyntax (line 353) | private void parseSyntax() {
method toBooleanQuery (line 451) | private Query toBooleanQuery(Element op) {
method toTermRangeQuery (line 581) | private TermRangeQuery toTermRangeQuery(Element fieldNameEle, LinkedLi...
method compare (line 646) | private int compare(Element e1, Element e2) {
class Element (line 676) | private static class Element {
method Element (line 680) | Element() {
method append (line 684) | void append(char c) {
method toString (line 688) | public String toString() {
method main (line 693) | public static void main(String[] args) {
FILE: src/main/java/org/wltea/analyzer/query/SWMCQueryBuilder.java
class SWMCQueryBuilder (line 48) | @SuppressWarnings("unused")
method create (line 56) | static Query create(String fieldName, String keywords) {
method doAnalyze (line 69) | private static List<Lexeme> doAnalyze(String keywords) {
method getSWMCQuery (line 87) | private static Query getSWMCQuery(String fieldName, List<Lexeme> lexem...
Condensed preview — 38 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (3,244K chars).
[
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 834,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
},
{
"path": ".gitignore",
"chars": 70,
"preview": "*.bak\n*.class\n*.log\n.classpath\n.project\n.settings\ntarget\n.idea\n*.iml\n\n"
},
{
"path": ".travis.yml",
"chars": 33,
"preview": "language: java\n\njdk:\n - openjdk8"
},
{
"path": "CONTRIBUTING.md",
"chars": 1,
"preview": "\n"
},
{
"path": "LICENSE",
"chars": 10974,
"preview": " Apache License\n Version 2.0, January 2004\n "
},
{
"path": "README-CLOUD.md",
"chars": 1859,
"preview": "\n## Solr-Cloud说明\n\n##### 因为`Solr-Cloud`中的配置文件是交由`zookeeper`进行管理的, 所以为了方便更新动态词典, 所以也要将动态词典文件上传至`zookeeper`中,目录与`solr`的配置文件"
},
{
"path": "README.md",
"chars": 5179,
"preview": "# ik-analyzer-solr\nik-analyzer for solr 7.x-8.x\n\n<!-- Badges section here. -->\n[ under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/cfg/DefaultConfig.java",
"chars": 5041,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/AnalyzeContext.java",
"chars": 10917,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/CJKSegmenter.java",
"chars": 3976,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/CN_QuantifierSegmenter.java",
"chars": 7051,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/CharacterUtil.java",
"chars": 3282,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/IKArbitrator.java",
"chars": 4526,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/IKSegmenter.java",
"chars": 4910,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/ISegmenter.java",
"chars": 1328,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/LetterSegmenter.java",
"chars": 9014,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/Lexeme.java",
"chars": 6645,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/LexemePath.java",
"chars": 6817,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/core/QuickSortSet.java",
"chars": 5091,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/dic/DictSegment.java",
"chars": 9276,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/dic/Dictionary.java",
"chars": 10434,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/dic/Hit.java",
"chars": 2472,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/lucene/IKAnalyzer.java",
"chars": 1999,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/lucene/IKTokenizer.java",
"chars": 4041,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/lucene/IKTokenizerFactory.java",
"chars": 6119,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/lucene/UpdateThread.java",
"chars": 2964,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/query/IKQueryExpressionParser.java",
"chars": 25031,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/java/org/wltea/analyzer/query/SWMCQueryBuilder.java",
"chars": 4576,
"preview": "/*\n * IK 中文分词 版本 8.5.0\n * IK Analyzer release 8.5.0\n *\n * Licensed to the Apache Software Foundation (ASF) under one or"
},
{
"path": "src/main/resources/IKAnalyzer.cfg.xml",
"chars": 398,
"preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE properties SYSTEM \"http://java.sun.com/dtd/properties.dtd\">\n<properties"
},
{
"path": "src/main/resources/dict/main2012.dic",
"chars": 1110206,
"preview": "他\n你\n切\n她\n我\n手\n有\n的\n见\nA股\nB股\nH股\nK线\nU盘\n一丁\n一丈\n一上\n一下\n一世\n一丙\n一业\n一丝\n一两\n一个\n一中\n一串\n一丸\n一举\n一久\n一义\n一乐\n一书\n一买\n一事\n一些\n一交\n一产\n一亩\n一亮\n一人\n一亿\n一仁\n一介\n"
},
{
"path": "src/main/resources/dict/quantifier.dic",
"chars": 713,
"preview": "丈\n下\n世\n世纪\n两\n个\n中\n串\n亩\n人\n介\n付\n代\n件\n任\n份\n伏\n伙\n位\n位数\n例\n倍\n像素\n元\n克\n克拉\n公亩\n公克\n公分\n公升\n公尺\n公担\n公斤\n公里\n公顷\n具\n册\n出\n刀\n分\n分钟\n分米\n划\n列\n则\n刻\n剂\n剑\n副\n加仑\n勺\n包\n"
},
{
"path": "src/main/resources/dynamicdic.txt",
"chars": 0,
"preview": ""
},
{
"path": "src/main/resources/ext.dic",
"chars": 0,
"preview": ""
},
{
"path": "src/main/resources/ik.conf",
"chars": 63,
"preview": "Wed Aug 01 00:00:00 CST 2021\nfiles=dynamicdic.txt\nlastupdate=0\n"
},
{
"path": "src/main/resources/stopword.dic",
"chars": 0,
"preview": ""
}
]
// ... and 1 more files (download for full content)
About this extraction
This page contains the full source code of the magese/ik-analyzer-solr7 GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 38 files (21.4 MB), approximately 1.2M tokens, and a symbol index with 229 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.